Skip to main content
Version: 0.4.x(Latest)

Introductionโ€‹

Assets() is the asset declaration entry point for source plugins. It binds the plugin's embedded filesystem through UseEmbeddedFiles(). The embedded filesystem contains the plugin's manifest files, frontend pages, SQL migration scripts, and i18n resources. The host loads these resources at startup to complete plugin integration. Dynamic plugins embed resources through WASM custom sections and do not require explicit binding.

Capability Phase: Declaration

Supported Plugin Types: Source plugins only

Capability Designโ€‹

Resource Directory Structureโ€‹

The standard plugin directory structure is as follows:

apps/lina-plugins/<plugin-id>/
โ”œโ”€โ”€ plugin.yaml # Plugin manifest [embedded]
โ”œโ”€โ”€ backend/ # Backend Go code [compiled, not embedded]
โ”‚ โ”œโ”€โ”€ plugin.go # Registration entry point
โ”‚ โ””โ”€โ”€ internal/ # Business logic
โ”œโ”€โ”€ frontend/ # Frontend resources [embedded]
โ”‚ โ””โ”€โ”€ dist/ # Build artifacts
โ””โ”€โ”€ manifest/ # Manifest resources [embedded]
โ”œโ”€โ”€ sql/ # SQL migration scripts
โ”‚ โ”œโ”€โ”€ install.sql # Installation script
โ”‚ โ”œโ”€โ”€ uninstall.sql # Uninstallation script
โ”‚ โ””โ”€โ”€ mock.sql # Mock data script
โ”œโ”€โ”€ i18n/ # Internationalization resources
โ”‚ โ”œโ”€โ”€ zh-Hans.yaml
โ”‚ โ””โ”€โ”€ en.yaml
โ””โ”€โ”€ config/ # Configuration templates
โ”œโ”€โ”€ config.yaml # Default configuration
โ””โ”€โ”€ config.example.yaml # Configuration example

Embedded Filesystem Bindingโ€‹

Source plugins embed static resources into the binary via UseEmbeddedFiles(). The embedding scope covers only the manifest files, frontend resources, and the manifest/ directory's operational resources -- backend Go source code is excluded:

Resource Typesโ€‹

Resource TypeDirectoryDescription
Manifest fileplugin.yamlPlugin identity, dependencies, menus, permissions, and other declarations
Frontend resourcesfrontend/dist/Frontend build artifacts, hosted by the host at /x-assets/{plugin-id}/{version}/
SQL migrationmanifest/sql/Installation, uninstallation, and mock data scripts; must be idempotent
i18n resourcesmanifest/i18n/Multilingual translation files
Configuration templatesmanifest/config/Plugin default configuration and configuration examples

Frontend Resource Hostingโ€‹

The host serves plugin frontend resources under the /x-assets/{plugin-id}/{version}/ path. Plugins declare directories to be hosted through the public_assets field in plugin.yaml:

public_assets:
- source: frontend/dist
mount: /
index: index.html
FieldDescription
sourceSource directory path within the plugin
mountMount path
indexDefault index file

SQL Migration Scriptsโ€‹

SQL migration scripts are located in the manifest/sql/ directory. The host executes them during plugin installation and uninstallation:

ScriptExecution TimingDescription
install.sqlPlugin installationCreates table structures and initializes data
uninstall.sqlPlugin uninstallationCleans up table structures and data
mock.sqlDevelopment environmentInserts mock data

SQL scripts must be idempotent, using IF NOT EXISTS or IF EXISTS to ensure repeated execution does not cause errors. Tables for multi-tenant plugins must include a tenant_id column.

Internationalization Resourcesโ€‹

Internationalization resources are located in the manifest/i18n/ directory in YAML format:

# manifest/i18n/zh-Hans.yaml
menu:
dashboard: ไปช่กจ็›˜
reports: ๆŠฅ่กจ
settings: ่ฎพ็ฝฎ

messages:
welcome: ๆฌข่ฟŽไฝฟ็”จ
error.notFound: ๆœชๆ‰พๅˆฐ่ต„ๆบ
# manifest/i18n/en.yaml
menu:
dashboard: Dashboard
reports: Reports
settings: Settings

messages:
welcome: Welcome
error.notFound: Resource not found

The host loads internationalization resources when the plugin is enabled for runtime translation use.

Interface Definitionโ€‹

Source Plugin Interfaceโ€‹

Source plugins declare their embedded filesystem through Assets():

MethodDescription
UseEmbeddedFilesBinds the plugin's embedded filesystem

AssetDeclarations interface definition:

type AssetDeclarations interface {
UseEmbeddedFiles(fileSystem fs.FS)
}

Dynamic Plugin Resource Managementโ€‹

Dynamic plugins embed resources through WASM custom sections without explicit binding. The build tool automatically embeds the following resources into the .wasm artifact:

Custom SectionContent
lina.plugin.manifestPlugin identity manifest
lina.plugin.frontend.assetsFrontend resources
lina.plugin.i18n.assetsInternationalization resources
lina.plugin.apidoc.i18n.assetsAPI documentation i18n resources
lina.plugin.install.sqlInstallation SQL script
lina.plugin.uninstall.sqlUninstallation SQL script
lina.plugin.mock.sqlMock data SQL script
lina.plugin.manifest.resourcesManifest resource files

Usageโ€‹

Source Plugin Usageโ€‹

Source plugins bind their embedded filesystem in init() through Assets():

package main

import (
"embed"

"lina-core/pkg/plugin/pluginhost"
)

//go:embed plugin.yaml all:manifest all:frontend/dist
var pluginFS embed.FS

func init() {
plugin := pluginhost.NewDeclarations("my-author-my-domain-my-cap")
plugin.Assets().UseEmbeddedFiles(pluginFS)

if err := pluginhost.RegisterSourcePlugin(plugin); err != nil {
panic(err)
}
}

Embedded Filesystem Accessโ€‹

The host accesses the plugin's embedded filesystem through SourcePluginDefinition.GetEmbeddedFiles():

// Read plugin manifest
manifestData, err := fs.ReadFile(embeddedFS, "plugin.yaml")

// Read SQL script
installSQL, err := fs.ReadFile(embeddedFS, "manifest/sql/install.sql")

// Read internationalization resources
i18nData, err := fs.ReadFile(embeddedFS, "manifest/i18n/zh-Hans.yaml")

Dynamic Plugin Resource Managementโ€‹

Dynamic plugin resources are automatically embedded into the .wasm artifact at build time. The build tool scans the plugin directory and generates corresponding custom sections:

# Build a dynamic plugin
make wasm p=my-plugin

The build tool automatically:

  1. Reads plugin.yaml and embeds the lina.plugin.manifest section
  2. Scans frontend/dist/ and embeds the lina.plugin.frontend.assets section
  3. Scans manifest/i18n/ and embeds the lina.plugin.i18n.assets section
  4. Scans manifest/sql/ and embeds the corresponding SQL sections
  5. Scans manifest/resources/ and embeds the lina.plugin.manifest.resources section

Design Constraintsโ€‹

  • Assets() is limited to source plugins. Dynamic plugins embed resources through WASM custom sections and do not require explicit binding.
  • The embedded filesystem is read-only. Plugins cannot modify embedded resources at runtime.
  • SQL scripts must be idempotent. Use IF NOT EXISTS or IF EXISTS to ensure repeated execution does not cause errors.
  • Multi-tenant tables require a tenant_id column. The host checks table structures for tenant-aware plugins.
  • Frontend resources are hosted by the host. Plugins should not self-host static resources; they should declare them through public_assets.
  • Internationalization resources use YAML format. The host uniformly parses i18n files in YAML format.