Criando plugins personalizados
Criando plugins personalizados
Se você precisar de rotas de API personalizadas ou de lógica em segundo plano, implemente um plugin do AppKit. A maneira mais rápida é usar a CLI:
# Interativo
npx @databricks/appkit plugin create
# Não interativo
npx @databricks/appkit plugin create --placement in-repo --path plugins/my-plugin --name my-plugin --description "My plugin" --forcePara entender melhor a estrutura do plugin, continue lendo.
Exemplo básico de plugin
Escreva o manifesto em JSON, importe-o e associe-o a uma subclasse de Plugin por meio de static manifest. Exporte com toPlugin():
// my-plugin/manifest.json
{
"$schema": "https://databricks.github.io/appkit/schemas/plugin-manifest.schema.json",
"name": "my-plugin",
"displayName": "My Plugin",
"description": "A custom plugin",
"resources": {
"required": [
{
"type": "secret",
"alias": "apiKey",
"resourceKey": "api-key",
"description": "API key for external service",
"permission": "READ",
"fields": {
"scope": { "env": "MY_SECRET_SCOPE", "description": "Secret scope" },
"key": { "env": "MY_API_KEY", "description": "Secret key name" }
}
}
],
"optional": []
}
}// my-plugin/index.ts
import { Plugin, toPlugin, type PluginManifest } from "@databricks/appkit";
import manifest from "./manifest.json";
class MyPlugin extends Plugin {
static manifest = manifest as PluginManifest<"my-plugin">;
async setup() {
// Inicialize seu plugin
}
myCustomMethod() {
// Alguma implementação
}
async shutdown() {
// Libere os recursos
}
exports() {
return {
myCustomMethod: this.myCustomMethod
}
}
}
export const myPlugin = toPlugin(MyPlugin);O JSON é a superfície canônica de autoria — é o que o appkit plugin sync lê ao agregar manifestos para os modelos. Para o contrato completo do manifesto v2.0 (recursos, descritores de descoberta, regras de scaffolding), consulte Manifesto do plugin.
Recursos dependentes de configuração
O manifesto define os recursos como required (sempre necessários) ou optional (podem ser necessários).
Para recursos que se tornam obrigatórios conforme a configuração do plugin, implemente um método estático
getResourceRequirements(config):
interface MyPluginConfig extends BasePluginConfig {
enableCaching?: boolean;
}
class MyPlugin extends Plugin<MyPluginConfig> {
static manifest = {
name: "myPlugin",
displayName: "My Plugin",
description: "A plugin with optional caching",
resources: {
required: [
{ type: "sql_warehouse", alias: "warehouse", resourceKey: "sqlWarehouse", description: "Query execution", permission: "CAN_USE", fields: { id: { env: "DATABRICKS_WAREHOUSE_ID" } } }
],
optional: [
// Listado como opcional no manifesto para análise estática
{ type: "database", alias: "cache", resourceKey: "cache", description: "Query result caching (if enabled)", permission: "CAN_CONNECT_AND_CREATE", fields: { instance_name: { env: "DATABRICKS_CACHE_INSTANCE" }, database_name: { env: "DATABRICKS_CACHE_DB" } } }
]
}
} satisfies PluginManifest<"myPlugin">;
// Runtime: converte recursos opcionais em obrigatórios conforme a configuração
static getResourceRequirements(config: MyPluginConfig) {
const resources = [];
if (config.enableCaching) {
// Quando o cache está ativado, o Database passa a ser obrigatório
resources.push({
type: "database",
alias: "cache",
resourceKey: "cache",
description: "Query result caching",
permission: "CAN_CONNECT_AND_CREATE",
fields: {
instance_name: { env: "DATABRICKS_CACHE_INSTANCE" },
database_name: { env: "DATABRICKS_CACHE_DB" },
},
required: true // Marca como obrigatório em runtime
});
}
return resources;
}
}Esse padrão permite:
- Que ferramentas estáticas (CLI, documentação) exibam todos os recursos possíveis
- Que a validação em runtime aplique os recursos com base na configuração real
Principais pontos de extensão
- Injeção de rotas: implemente
injectRoutes()para adicionar endpoints personalizados usandoIAppRouter - Hooks de ciclo de vida: sobrescreva os métodos
setup()eshutdown() - Serviços compartilhados:
- Gerenciamento de cache: acesse o serviço de cache por meio de
this.cache. ConsulteCacheConfigpara a configuração. - Telemetria: instrumente seu plugin com traces e métricas por meio de
this.telemetry. ConsulteITelemetry.
- Gerenciamento de cache: acesse o serviço de cache por meio de
- Interceptadores de execução: use
execute()eexecuteStream()comStreamExecutionSettingspara obter cache, retry e timeout automáticos, além dos atributos de span de telemetria (execution.context,caller.id)
Consumindo seu plugin programaticamente
Se desejar, você pode oferecer uma forma de consumir seu plugin programaticamente usando o objeto AppKit.
Para isso, seu plugin precisa implementar o método exports, retornando um objeto com os métodos que deseja expor. Com base no exemplo anterior, o plugin poderia ser consumido assim:
const AppKit = await createApp({
plugins: [
server({ port: 8000 }),
analytics(),
myPlugin(),
],
});
AppKit.myPlugin.myCustomMethod();Consulte a referência da API Plugin para a documentação completa.