Skip to main content

plugin

Package plugin defines the Drift plugin authoring API.

Plugins are Go modules that contribute build-time and runtime native behaviour to a Drift project. A plugin module exports a single typed Plugin value at <module>/plugin and is wired into a project via drift.yaml.

The wire contract between the Drift CLI and the generated bridge binary (envelope, response, op types, config schema) lives in the protocol sub-package.

The authoring guide (website-docs/guides/plugin-authoring.md) covers writing a plugin and lists every op. examples/plugins/hello is the smallest complete plugin, quoted by the guide; the first-party plugins under plugins/ (splash, firebase) are full references.

Constants​

SwiftPM requirement kinds, re-exported from protocol for plugin authors.

const (
SPMFrom = protocol.SPMFrom
SPMExact = protocol.SPMExact
SPMBranch = protocol.SPMBranch
SPMRevision = protocol.SPMRevision
SPMUpToNextMajor = protocol.SPMUpToNextMajor
SPMUpToNextMinor = protocol.SPMUpToNextMinor
SPMRange = protocol.SPMRange
)

TestAppID is the AppID of test contexts (NewTestCtx, NewTestCtxAt, NewTestCtxFor).

const TestAppID = "com.example.app"

func Main​

func Main(bindings ...Binding)

Main is the bridge tool entry point. The generated tools/drift-plugins/main.go calls Main with one Binding per configured plugin.

Main panics on duplicate plugin names: the bridge fails fast at startup rather than letting two plugins with the same friendly name confuse later diagnostics. It also panics on duplicate package paths.

type AndroidDrawablesScope​

AndroidDrawablesScope writes raw bitmaps under res/drawable-nodpi: Android does not scale them by screen density, so size them where they are used (a layout, a drawable XML's item size).

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

func (*AndroidDrawablesScope) AddBitmap​

func (s *AndroidDrawablesScope) AddBitmap(name string, content []byte)

type AndroidManifestScope​

AndroidManifestScope records AndroidManifest.xml mutations.

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

func (*AndroidManifestScope) AddIntentFilter​

func (s *AndroidManifestScope) AddIntentFilter(activity string, xml string)

func (*AndroidManifestScope) AddMetaData​

func (s *AndroidManifestScope) AddMetaData(parent, name, value string)

func (*AndroidManifestScope) AddPermission​

func (s *AndroidManifestScope) AddPermission(name string)

func (*AndroidManifestScope) AddPermissionMaxSDK​

func (s *AndroidManifestScope) AddPermissionMaxSDK(name string, maxSDK int)

AddPermissionMaxSDK declares a permission requested only up to API level maxSDK (android:maxSdkVersion), such as READ_EXTERNAL_STORAGE, which READ_MEDIA_IMAGES replaced in API 33.

func (*AndroidManifestScope) AddReceiver​

func (s *AndroidManifestScope) AddReceiver(xml string)

AddReceiver declares a <receiver> in <application>, for a plugin BroadcastReceiver the system starts. xml is the whole element, with the fully qualified class as android:name; a receiver with an intent filter must set android:exported. For example:

<receiver android:name="com.example.alarms.AlarmReceiver" android:exported="false" />

func (*AndroidManifestScope) AddService​

func (s *AndroidManifestScope) AddService(xml string)

AddService declares a <service> element in <application>, written as given (xml), for a plugin class the system starts. android:name is the fully qualified class; a service with intent filters sets android:exported. For example:

<service android:name="com.example.push.PushService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

func (*AndroidManifestScope) SetActivityAttr​

func (s *AndroidManifestScope) SetActivityAttr(activity, attr, value string)

func (*AndroidManifestScope) SetActivityTheme​

func (s *AndroidManifestScope) SetActivityTheme(activity, theme string)

SetActivityTheme is sugar for SetActivityAttr(activity, "android:theme", theme).

type AndroidResourcesScope​

AndroidResourcesScope groups res/values/* and arbitrary resource writers.

type AndroidResourcesScope struct {

// Colors values are Drift hex colours ("#RRGGBB" or "#RRGGBBAA", alpha
// last, as the `hex` config tag accepts); Drift writes them in Android's
// alpha-first format.
Colors *AndroidValuesScope
// Strings values are literal text: Drift escapes them for Android's
// string resource syntax (apostrophes, quotes, backslashes, a leading
// @ or ?, whitespace, %), so the app reads back exactly the value.
Strings *AndroidValuesScope
Styles *AndroidStylesScope
// contains filtered or unexported fields
}

func (*AndroidResourcesScope) WriteXML​

func (s *AndroidResourcesScope) WriteXML(relPath, content string)

WriteXML writes an arbitrary resource XML file under res/<relPath>. relPath is slash-separated and rooted at res/.

type AndroidScope​

AndroidScope groups Android-targeted ops.

type AndroidScope struct {
Manifest *AndroidManifestScope
Resources *AndroidResourcesScope
Drawables *AndroidDrawablesScope
Sources *AndroidSourcesScope
// contains filtered or unexported fields
}

func (*AndroidScope) AddAppModuleFile​

func (s *AndroidScope) AddAppModuleFile(name string, content []byte)

AddAppModuleFile records a file to drop into the Android app module directory, next to app/build.gradle. Use for build-time config that Gradle plugins read from there, such as Firebase's google-services.json. name is a plain file name; scaffold-owned names (build.gradle, src, ...) are rejected.

func (*AndroidScope) AddGradleDependency​

func (s *AndroidScope) AddGradleDependency(configuration, coord string)

AddGradleDependency records a single Gradle dependency line to be inserted into the app's build.gradle dependencies block. Configuration is the Gradle dependency configuration ("implementation", "api", etc.); coord is the full coordinate including version ("group:artifact:version"). Pin versions explicitly; floating versions in generated build files are a CI heisenbug factory.

func (*AndroidScope) ApplyGradlePlugin​

func (s *AndroidScope) ApplyGradlePlugin(id, version string)

ApplyGradlePlugin records an `apply plugin: "<id>"` line for the app's build.gradle, inserted after the android { } block (plugins such as Firebase's com.google.gms.google-services need the android block configured first). A non-empty version also declares the plugin in the project-level build.gradle plugins { } block so Gradle can resolve it; pass "" when the plugin is already on the build classpath.

func (*AndroidScope) Plugin​

func (s *AndroidScope) Plugin(class string)

Plugin records the fully qualified Kotlin class the app instantiates for this plugin, e.g. com.example.camera.CameraPlugin. The class implements com.drift.runner.DriftPlugin and has a no-argument constructor; the host drives it through the plugin lifecycle (register, attach/detach). Ship its source with Sources.

type AndroidSourcesScope​

AndroidSourcesScope writes Kotlin sources to the app source tree.

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

func (*AndroidSourcesScope) AddFS​

func (s *AndroidSourcesScope) AddFS(pkg string, sources embed.FS, root string)

AddFS walks the supplied embed.FS rooted at root and records one OpAddKotlinSource per file. Files land under app/src/main/java/<packagePath>/<relpath> where packagePath is the dot-separated Kotlin package converted to slashes.

func (*AndroidSourcesScope) AddFile​

func (s *AndroidSourcesScope) AddFile(pkg, rel string, content []byte)

AddFile records a single Kotlin file under the given package.

type AndroidStylesScope​

AndroidStylesScope handles res/values/styles.xml entries.

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

func (*AndroidStylesScope) Set​

func (s *AndroidStylesScope) Set(name, parent string, items map[string]string)

Set records a style with the given parent and key/value items.

type AndroidValuesScope​

AndroidValuesScope records one kind of res/values entry (colors or strings) into Drift's plugin-owned values file for that kind.

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

func (*AndroidValuesScope) Set​

func (s *AndroidValuesScope) Set(name, value string)

Set records the value resource name = value.

type Binding​

Binding pairs a plugin value with the drift.yaml package path it was loaded from. The bridge tool calls Bind for each configured plugin and forwards the slice to Main; the slice is the entire registry for the run.

type Binding struct {
Package string
Name string
// contains filtered or unexported fields
}

func Bind​

func Bind[T any](pkgPath string, p Plugin[T]) Binding

Bind wraps a typed Plugin[T] into a non-generic Binding suitable for Main. Bind preserves T via closure capture so config decoding can target the exact struct without reflecting back to a runtime type.

func (Binding) Build​

func (b Binding) Build(ctx *BuildCtx, configYAML []byte) error

Build runs the plugin's Build for raw drift.yaml config bytes, checked against the config schema and defaulted first. The bridge calls it for each configured plugin; plugin tests call it to build exactly as the bridge does (see NewTestCtx).

func (Binding) Schema​

func (b Binding) Schema() protocol.PluginSchema

Schema returns the captured PluginSchema for the binding.

type BuildCtx​

BuildCtx is passed to Plugin.Build. It records ops on platform-specific surfaces and exposes shared helpers like ResolveAsset. Plugins MUST NOT touch disk directly during Build; all mutations flow through op recorders so the CLI can validate the full op list before applying it.

type BuildCtx struct {

// IOS records ops for iOS builds, both xcodeproj ("ios") and xtool.
// Plugins record for every platform unconditionally; the CLI applies
// only the ops for the platform being built.
IOS *IOSScope
// Android records ops for Android builds.
Android *AndroidScope
// contains filtered or unexported fields
}

func NewTestCtx​

func NewTestCtx() *BuildCtx

NewTestCtx returns a BuildCtx for plugin unit tests, building for every platform (Platform() is "all"). Run a plugin with Bind(pkg, Plugin).Build(ctx, configYAML), which checks and defaults the config like the bridge, then inspect Ops() and Err().

func NewTestCtxAt​

func NewTestCtxAt(projectRoot string) *BuildCtx

NewTestCtxAt returns a BuildCtx whose projectRoot is the supplied path so ResolveAsset reads from a real on-disk directory. Use this when a Build implementation needs ResolveAsset to succeed during testing.

func NewTestCtxFor​

func NewTestCtxFor(projectRoot, platform string) *BuildCtx

NewTestCtxFor is NewTestCtxAt building for one platform ("ios", "xtool" or "android"), for a Build that depends on Platform().

func (*BuildCtx) AppID​

func (b *BuildCtx) AppID() string

AppID returns the app's identifier from drift.yaml (app.id): the iOS bundle identifier and the Android application id, which Drift keeps equal. Plugins check SDK config files that name the app against it.

func (*BuildCtx) BuildDir​

func (b *BuildCtx) BuildDir() string

BuildDir returns the absolute build directory (managed or ejected); empty under drift plugin sync, which builds nothing.

func (*BuildCtx) Err​

func (b *BuildCtx) Err() error

Err returns every error recorders captured during Build (invalid input, unreadable embed.FS), joined, or nil. The bridge runtime consults it after Plugin.Build returns; plugin unit tests should check it too. Invalid ops are reported here and never recorded.

func (*BuildCtx) NativeConfig​

func (b *BuildCtx) NativeConfig(v any)

NativeConfig records v, which must marshal (encoding/json) to a JSON object, as the plugin's config for its native code on every platform: native code reads it as DriftPluginHost.config, a dictionary (iOS) or map (Android) of JSON-like values, empty when a plugin records none. Use it for build-time choices native code acts on, such as which permission kinds to register or a splash screen's colours, rather than Info.plist keys, resources or generated sources. Call it at most once per Build.

Values arrive as JSON decodes them natively: numbers as NSNumber (iOS) and Int, Long or Double (Android), so read them as numbers, not a specific integer type.

func (*BuildCtx) Ops​

func (b *BuildCtx) Ops() []protocol.Op

Ops returns the ops recorded so far in the context.

func (*BuildCtx) Platform​

func (b *BuildCtx) Platform() string

Platform returns the platform being built: "android", "ios" (xcodeproj) or "xtool". drift plugin sync, which checks config without building, and test contexts from NewTestCtx and NewTestCtxAt return "all": record for every platform the config enables. Most plugins never need to branch on it.

func (*BuildCtx) Plugin​

func (b *BuildCtx) Plugin() string

Plugin returns the package path of the plugin currently being built.

func (*BuildCtx) PluginName​

func (b *BuildCtx) PluginName() string

PluginName returns the friendly name of the plugin currently being built.

func (*BuildCtx) ProjectRoot​

func (b *BuildCtx) ProjectRoot() string

ProjectRoot returns the absolute path of the user's project root.

func (*BuildCtx) ResolveAsset​

func (b *BuildCtx) ResolveAsset(rel string) ([]byte, error)

ResolveAsset reads an asset at a path relative to the project root. Plugin authors use this to bundle user-provided images, fonts, etc.

type Color​

Color is a colour in Drift's hex format, "#RRGGBB" or "#RRGGBBAA" with alpha last: the format the `hex` config tag accepts and AndroidResourcesScope.Colors takes. Use it to write a colour into a platform file a plugin generates itself (a storyboard, a values-night XML), which must use that platform's own format.

type Color = protocol.Color

func ParseColor​

func ParseColor(s string) (Color, error)

ParseColor parses Drift's hex format. Six digits mean opaque.

type IOSAssetsScope​

IOSAssetsScope records additions to Runner/Assets.xcassets.

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

func (*IOSAssetsScope) AddImageSet​

func (s *IOSAssetsScope) AddImageSet(name string, img []byte)

AddImageSet adds a single-resolution image set named `name` containing img. The image is treated as the 1x universal entry.

type IOSPlistScope​

IOSPlistScope records edits to one iOS plist: Info.plist or the entitlements.

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

func (*IOSPlistScope) AppendArrayDict​

func (s *IOSPlistScope) AppendArrayDict(key string, dict map[string]any)

AppendArrayDict adds dict to the array of dictionaries at key (created if absent), alongside what the template and other plugins put there. For a URL scheme, use IOSScope.AddURLScheme.

func (*IOSPlistScope) AppendArrayItem​

func (s *IOSPlistScope) AppendArrayItem(key, value string)

AppendArrayItem adds value to the array at key (created if absent), alongside what the template and other plugins put there, e.g. a UIBackgroundModes entry.

func (*IOSPlistScope) SetBool​

func (s *IOSPlistScope) SetBool(key string, value bool)

func (*IOSPlistScope) SetDict​

func (s *IOSPlistScope) SetDict(key string, dict map[string]any)

func (*IOSPlistScope) SetString​

func (s *IOSPlistScope) SetString(key, value string)

func (*IOSPlistScope) SetStringArray​

func (s *IOSPlistScope) SetStringArray(key string, values []string)

type IOSScope​

IOSScope groups iOS-targeted ops.

type IOSScope struct {

// Info edits the app's Info.plist.
Info *IOSPlistScope
// Entitlements edits the app's code-signing entitlements
// (Runner.entitlements), e.g. aps-environment for push notifications.
// Automatic signing enables the matching App ID capabilities.
Entitlements *IOSPlistScope
Assets *IOSAssetsScope
Storyboards *IOSStoryboardsScope
Sources *IOSSourcesScope
// contains filtered or unexported fields
}

func (*IOSScope) AddBundleResource​

func (s *IOSScope) AddBundleResource(name string, content []byte)

AddBundleResource records a file to copy into the root of the iOS app bundle, where Bundle.main and UIImage(named:) find it. Use for files that SDKs look up in the main bundle (Firebase's GoogleService-Info.plist), images, fonts, JSON data, or ML models. name is a plain file name: both iOS build paths flatten resources into the bundle root.

func (*IOSScope) AddPackageDependency​

func (s *IOSScope) AddPackageDependency(url string, req SPMRequirement, products []string)

AddPackageDependency records a SwiftPM dependency for the iOS app to link. Both build paths (xcodeproj and xtool) consume the same sidecar Drift/Plugins/Package.swift; one call produces one `.package(url:...)` declaration plus one `.product(name📦)` per entry in products. Products are referenced against the package identity derived from the URL (e.g. "firebase-ios-sdk"), matching SwiftPM's own resolution rule.

func (*IOSScope) AddURLScheme​

func (s *IOSScope) AddURLScheme(scheme string)

AddURLScheme registers scheme as one the app opens, such as an OAuth redirect's, as an Info.plist CFBundleURLTypes entry named after it. A URL with it is offered to the plugins' openURL hooks, then to Drift's deep links. On Android, register it with Android.Manifest.AddIntentFilter.

func (*IOSScope) Plugin​

func (s *IOSScope) Plugin(class string)

Plugin records the Swift class the app instantiates for this plugin. The class conforms to DriftPlugin and has a no-argument initializer; the host drives it through the plugin lifecycle (register, attach/detach, app hooks). Ship its source with Sources.

type IOSSourcesScope​

IOSSourcesScope records Swift sources to drop into the iOS target.

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

func (*IOSSourcesScope) AddFS​

func (s *IOSSourcesScope) AddFS(group string, sources embed.FS, root string)

AddFS walks the supplied embed.FS rooted at root (slash-separated) and records one Swift source per file, at <group>/<relpath> in the plugin's own module (Drift/Plugins/Sources/DriftPlugin_<name>).

func (*IOSSourcesScope) AddFile​

func (s *IOSSourcesScope) AddFile(group, rel string, content []byte)

AddFile records a single Swift source file at <group>/<rel> in the plugin's own module.

type IOSStoryboardsScope​

IOSStoryboardsScope records storyboard mutations.

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

func (*IOSStoryboardsScope) ReplaceLaunchScreen​

func (s *IOSStoryboardsScope) ReplaceLaunchScreen(content string)

ReplaceLaunchScreen replaces Runner/LaunchScreen.storyboard with the supplied content. Two plugins that try to replace the launch screen with divergent content conflict.

type Plugin​

Plugin is the generic plugin interface. Plugin authors implement Build to emit ops on the supplied BuildCtx. Name returns the short friendly identifier used in diagnostics and the drift plugin list NAME column.

type Plugin[T any] interface {
Name() string
Build(ctx *BuildCtx, cfg T) error
}

type SPMRequirement​

SPMRequirement is a SwiftPM version requirement for IOSScope.AddPackageDependency. It is the wire type itself, aliased so plugin authors need only this package.

type SPMRequirement = protocol.SPMRequirement

func SPMRequirementFrom​

func SPMRequirementFrom(version string) SPMRequirement

SPMRequirementFrom is sugar for the most common form (`from:`, which is SwiftPM's up-to-next-major shorthand).

type SPMRequirementKind​

SPMRequirementKind names one of SwiftPM's `.package(url:...)` version requirement forms.

type SPMRequirementKind = protocol.SPMRequirementKind

Generated by gomarkdoc