Çöññéçţöŕ Šýšţéḿ
Çöññéçţöŕš þŕöṽîđé ƃîđîŕéçţîöñàļ šýñç ƃéţŵééñ neokapi àñđ éẋţéŕñàļ çöñţéñţ šöüŕçéš. Ţĥéý þüļļ çöñţéñţ îñţö ţĥé Çöñţéñţ Šţöŕé àñđ þüšĥ ŕéšüļţš ƃàçķ. Ţĥîš þàĝé çöṽéŕš ţĥé Ĝö îñţéŕƒàçéš; ƒöŕ çöñƒîĝüŕîñĝ çöññéçţöŕš öñ à šéŕṽéŕ, šéé Çöññéçţöŕš.
Çöññéçţöŕ Îñţéŕƒàçéš
Ţĥé îñţéŕƒàçéš ļîṽé îñ bowrain/core/connector. Ţŵö þéŕšþéçţîṽéš ŕéǫüîŕé ţŵö îñţéŕƒàçéš, ƃöţĥ šĥàŕîñĝ à çöḿḿöñ ƃàšé:
// ConnectorBase contains shared connector identity and lifecycle methods.
type ConnectorBase interface {
ID() string
Name() string
Category() Category
Status(ctx context.Context) (*SyncStatus, error)
Configure(config map[string]string) error
Close() error
}
// IntegrationConnector represents a system that Bowrain reaches into.
// Used by server-side integrations (WordPress, Figma, HubSpot, filesystem, Git).
type IntegrationConnector interface {
ConnectorBase
// Fetch retrieves source content FROM the external system INTO Bowrain.
Fetch(ctx context.Context, opts FetchOptions) ([]*ContentItem, error)
// Publish sends content FROM Bowrain TO the external system.
Publish(ctx context.Context, items []*ContentItem, opts PublishOptions) error
// List returns available content items without fetching full content.
List(ctx context.Context) ([]*ContentItem, error)
}
// SourceConnector represents a content source that pushes to and pulls from
// Bowrain. Used by systems outside Bowrain (kapi CLI, Git hooks, CI/CD).
type SourceConnector interface {
ConnectorBase
// Push sends source content FROM the source system TO Bowrain.
Push(ctx context.Context, opts PushOptions) (*PushResult, error)
// Pull retrieves content FROM Bowrain TO the source system.
Pull(ctx context.Context, opts PullOptions) (*PullResult, error)
}
IntegrationConnector üšéš ƒéţçĥ/þüƃļîšĥ ţéŕḿîñöļöĝý ƒŕöḿ Bowrain'š þéŕšþéçţîṽé; SourceConnector üšéš þüšĥ/þüļļ ţéŕḿîñöļöĝý ƒŕöḿ ţĥé šöüŕçé šýšţéḿ'š þéŕšþéçţîṽé. Ţĥé ƒüļļ öþţîöñ àñđ ŕéšüļţ ţýþéš àŕé đéçļàŕéđ àļöñĝšîđé ţĥé îñţéŕƒàçéš îñ ţĥé çöññéçţöŕ þàçķàĝé.
Çàţéĝöŕîéš
Çöññéçţöŕš àŕé öŕĝàñîžéđ ƃý çàţéĝöŕý:
| Çàţéĝöŕý | Đéšçŕîþţîöñ | Ƃüîļţ-îñ |
|---|---|---|
file | Ļöçàļ ƒîļéšýšţéḿ çöñţéñţ | ƑîļéÇöññéçţöŕ |
code | Šöüŕçé çöđé ŕéþöšîţöŕîéš | ĜîţÇöññéçţöŕ, ƑöŕĝéÇöññéçţöŕ |
cms | Çöñţéñţ ḿàñàĝéḿéñţ šýšţéḿš | ŴöŕđÞŕéššÇöññéçţöŕ |
design | Đéšîĝñ ţööļš | ƑîĝḿàÇöññéçţöŕ |
marketing | Ḿàŕķéţîñĝ þļàţƒöŕḿš | ĤüƃŠþöţÇöññéçţöŕ |
analytics | Þŕöđüçţ àñàļýţîçš | ÞöšţĤöĝÇöññéçţöŕ (ļöçàļé đéḿàñđ; çàŕŕîéš ñö çöñţéñţ) |
Ƃüîļţ-îñ Çöññéçţöŕš
ƑîļéÇöññéçţöŕ
Ŵŕàþš ţĥé FormatRegistry ţö ŕéàđ/ŵŕîţé çöñţéñţ ƒîļéš. Šîñĝļé-ţéñàñţ ĥöšţš öñļý; šéé Çöññéçţöŕ Ŕéĝîšţŕý:
config := map[string]string{
"path": "/path/to/content",
"format": "json", // Optional: auto-detected from extensions
}
ĜîţÇöññéçţöŕ
Çļöñé/þüļļ ŕéþöšîţöŕîéš àñđ đîšçöṽéŕ ŕéšöüŕçé ƒîļéš ṽîà ĝļöƃ þàţţéŕñš:
config := map[string]string{
"url": "https://github.com/org/repo.git",
"branch": "main",
"pattern": "src/locales/**/*.json",
}
ƑöŕĝéÇöññéçţöŕ
Ŵŕàþš ţĥé ĝîţ çöññéçţöŕ ƒöŕ ĜîţĤüƃ/ĜîţĻàƃ ŕéþöšîţöŕîéš àñđ àđđš ƃŕàñçĥ-àñđ-þüļļ-ŕéǫüéšţ đéļîṽéŕý: à þüšĥ ŵéƃĥööķ ţŕîĝĝéŕš ţĥé šéŕṽéŕ, àñđ ŕéšüļţš çöḿé ƃàçķ àš öñé þüļļ/ḿéŕĝé ŕéǫüéšţ ţĥàţ éṽéŕý đéļîṽéŕý üþđàţéš îñ þļàçé. Šéé ĜîţĤüƃ / ĜîţĻàƃ çöññéçţöŕ ƒöŕ çöñƒîĝüŕàţîöñ.
ŴöŕđÞŕéššÇöññéçţöŕ
ŔÉŠŢ ÀÞÎ îñţéĝŕàţîöñ ƒöŕ ŴöŕđÞŕéšš þöšţš. Üšé à ŴöŕđÞŕéšš àþþļîçàţîöñ þàššŵöŕđ, ñöţ ţĥé àççöüñţ ļöĝîñ þàššŵöŕđ (šéé ţĥé ŴöŕđÞŕéšš çöññéçţöŕ ĝüîđé):
config := map[string]string{
"url": "https://example.com",
"username": "editor",
"password": "xxxx xxxx xxxx xxxx xxxx xxxx", // application password
}
ƑîĝḿàÇöññéçţöŕ
ŔÉŠŢ ÀÞÎ ƒöŕ Ƒîĝḿà ţéẋţ ñöđéš ŵîţĥ ĐîšþļàýĤîñţš ƒŕöḿ ƃöüñđîñĝ ƃöẋéš:
config := map[string]string{
"token": "figma-personal-access-token",
"file_key": "abc123def456",
}
ĤüƃŠþöţÇöññéçţöŕ
ŔÉŠŢ ÀÞÎ ƒöŕ ĤüƃŠþöţ ÇḾŠ þàĝéš:
config := map[string]string{
"api_key": "hubspot-api-key",
}
Çöññéçţöŕ Ŕéĝîšţŕý
Ţĥé ŕéĝîšţŕý ļîṽéš îñ bowrain/core/connector; ţĥé çöñçŕéţé îḿþļéḿéñţàţîöñš àñđ ţĥéîŕ ŕéĝîšţŕàţîöñ ĥéļþéŕš ļîṽé îñ bowrain/connector.
Ŵĥîçĥ ţýþéš à ŕéĝîšţŕý öƒƒéŕš îš à šéçüŕîţý ƃöüñđàŕý, ñöţ à çàþàƃîļîţý ļîšţ, šö ţĥéŕé îš ñö "ŕéĝîšţéŕ éṽéŕýţĥîñĝ" ĥéļþéŕ; éàçĥ ĥöšţ ñàḿéš ţĥé šüŕƒàçé îţ îš:
| Ĥéļþéŕ | Ŕéĝîšţéŕš | Üšéđ ƃý |
|---|---|---|
RegisterServer | ƒöŕĝé, ŵöŕđþŕéšš, ƒîĝḿà, ĥüƃšþöţ | Bowrain šéŕṽéŕ, îñĝéšţ ŵöŕķéŕ |
RegisterForgeApp | ţĥé ƒöŕĝé çöññéçţöŕ îñ ĜîţĤüƃ Àþþ ḿöđé | Bowrain šéŕṽéŕ, ŵĥéñ à ĜîţĤüƃ Àþþ îš çöñƒîĝüŕéđ |
RegisterLocal | ƒîļé, ĝîţ, ƒöŕĝé, ŵöŕđþŕéšš, ƒîĝḿà, ĥüƃšþöţ | šîñĝļé-ţéñàñţ ĥöšţš |
RegisterRemote | ŵöŕđþŕéšš, ƒîĝḿà, ĥüƃšþöţ | đéšķţöþ àþþ |
À çöññéçţöŕ îš ƃüîļţ ƒŕöḿ à çöñƒîĝ ḿàþ, àñđ öñ à ḿüļţî-ţéñàñţ šéŕṽéŕ ţĥàţ ḿàþ àŕŕîṽéš öṽéŕ ţĥé ŵöŕķšþàçé çöññéçţöŕš ÀÞÎ ƒŕöḿ àñýöñé ĥöļđîñĝ PermManageConnectors. Ţĥé file àñđ git çöññéçţöŕš ţàķé à ƒîļéšýšţéḿ þàţĥ ƒŕöḿ ţĥàţ çöñƒîĝ, šö RegisterServer öḿîţš ţĥéḿ: à ţéñàñţ ḿüšţ ñöţ ƃé àƃļé ţö ñàḿé à þàţĥ öñ ţĥé ĥöšţ ţĥé šéŕṽéŕ ŕüñš öñ. Šéŕṽéŕ-šîđé ŵöŕķ ţĥàţ ĝéñüîñéļý ñééđš à ļöçàļ çĥéçķöüţ (ţĥé çöñţéẋţ šçàñ'š ŕéþöšîţöŕý ĥàŕṽéšţ, ƒöŕ éẋàḿþļé) çöñšţŕüçţš îţš çöññéçţöŕ đîŕéçţļý îñ Ĝö ŵîţĥ à þàţĥ ţĥé šéŕṽéŕ çĥöšé.
reg := connector.NewRegistry()
bowrainconn.RegisterServer(reg, formatReg) // forge, wordpress, figma, hubspot
// Create a connector instance
c, err := reg.NewConnector("wordpress", config)
// List available types
types := reg.List()
Éṽéŕý ŕéḿöţé çöññéçţöŕ'š ĤŢŢÞ çļîéñţ îš ƃüîļţ ƒŕöḿ à bowrain/safehttp þöļîçý, ƃéçàüšé à ƃàšé ÜŔĻ îñ à çöññéçţöŕ çöñƒîĝ îš ţéñàñţ îñþüţ àîḿéđ àţ ţĥé ñéţŵöŕķ ţĥé šéŕṽéŕ šîţš öñ. Ţĥé þöļîçý ŕéšöļṽéš àñđ ŕé-çĥéçķš ţĥé ĥöšţ àţ çöññéçţ ţîḿé, đîšàƃļéš éñṽîŕöñḿéñţ þŕöẋîéš, ŕé-àþþļîéš îţšéļƒ ţö éṽéŕý ŕéđîŕéçţ ĥöþ, àñđ ŕéƒüšéš ļööþƃàçķ, þŕîṽàţé, ļîñķ-ļöçàļ, ÇĜÑÀŢ, ḿüļţîçàšţ, àñđ üñšþéçîƒîéđ àđđŕéššéš. À ñéŵ çöññéçţöŕ ţĥàţ đîàļš à çöñƒîĝüŕéđ ĥöšţ ḿüšţ üšé îţ; core/httputil îš àƃöüţ ŢĻŠ àñđ ŕéţŕîéš, àñđ îš ñöţ à šüƃšţîţüţé.
Àţ ţĥé ÀÞÎ ļéṽéļ, çöññéçţöŕ îñšţàñçéš àŕé ŵöŕķšþàçé-šçöþéđ: ţĥéý àŕé çŕéàţéđ ŵîţĥ POST /api/v1/{workspace}/connectors àñđ àđđŕéššéđ üñđéŕ ţĥàţ ŵöŕķšþàçé. Šéé Çöññéçţöŕš ƒöŕ ţĥé šéţüþ ĝüîđéš.
Îḿþļéḿéñţîñĝ à Çüšţöḿ Çöññéçţöŕ
- Çŕéàţé à ţýþé îḿþļéḿéñţîñĝ
connector.IntegrationConnector - Ŕéĝîšţéŕ à ƒàçţöŕý ƒüñçţîöñ öñ ţĥé ŕéĝîšţŕý, ŵîţĥ ţĥé çöññéçţöŕ'š çàţéĝöŕý:
reg.Register("my-connector", connector.CategoryCMS,
func(config map[string]string) (connector.IntegrationConnector, error) {
return &MyConnector{config: config}, nil
})