Çöññéçţöŕ Šýšţéḿ
Çöññéçţöŕš šýñç çöñţéñţ îñ ƃöţĥ đîŕéçţîöñš ƃéţŵééñ Ƃöŵŕàîñ àñđ éẋţéŕñàļ çöñţéñţ šöüŕçéš. Ţĥéý þüļļ çöñţéñţ îñţö ţĥé Çöñţéñţ Šţöŕé àñđ þüšĥ ŕéšüļţš ƃàçķ. Ţĥé šéçţîöñš ƃéļöŵ çöṽéŕ ţĥé Ĝö îñţéŕƒàçéš. Ţö çöñƒîĝüŕé çöññéçţöŕš öñ à šéŕṽéŕ, šéé Çöññéçţöŕš.
Çöññéçţöŕ Îñţéŕƒàçéš
Ţĥé îñţéŕƒàçéš ļîṽé îñ 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 üšéš ƒéţçĥ/þüƃļîšĥ ţéŕḿîñöļöĝý ƒŕöḿ Ƃöŵŕàîñ'š þéŕšþéçţîṽé; 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 | ƒöŕĝé, ŵöŕđþŕéšš, ƒîĝḿà, ĥüƃšþöţ | Ƃöŵŕàîñ šéŕṽéŕ, îñĝéšţ ŵöŕķéŕ |
RegisterForgeApp | ţĥé ƒöŕĝé çöññéçţöŕ îñ ĜîţĤüƃ Àþþ ḿöđé | Ƃöŵŕàîñ šéŕṽéŕ, ŵĥéñ à ĜîţĤüƃ Àþþ îš çöñƒîĝüŕéđ |
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
})