Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ The official [Lark/Feishu](https://www.larksuite.com/) CLI tool, maintained by t
| 🕐 Attendance | Query personal attendance check-in records |
| ✍️ Approval | Query approval tasks, approve/reject/transfer tasks, cancel and CC instances |
| 🎯 OKR | Query, create, update OKRs; manage objective & key results, alignments, indicators and progress. |
| 🧑‍💼 Hire | Recruitment: jobs, talents, applications, offers — query, create, update; track stages & onboarding |
| 📋 Project | Meegle — manage work items, schedules, and data via the standalone [meegle-cli](https://github.com/larksuite/meegle-cli) (install separately) |
| 🔗 Apps | Develop, deploy HTML, web pages and applications |

Expand Down
57 changes: 42 additions & 15 deletions internal/registry/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ var registryFS embed.FS
// embeddedMetaJSON is set by loader_embedded.go when meta_data.json is compiled in.
var embeddedMetaJSON []byte

// embeddedBuiltinJSON is set by loader_embedded.go from meta_data_builtin.json.
// It holds services the remote api_definition endpoint does not serve (hire),
// and is always merged into the registry.
var embeddedBuiltinJSON []byte

// EmbeddedMetaJSON returns the raw embedded meta_data.json bytes for callers
// that need to parse key order or other JSON-level structure not exposed by
// LoadFromMeta (which loses map insertion order).
Expand All @@ -35,26 +40,31 @@ var (
embeddedParseOnce sync.Once
)

// parseEmbeddedServices parses embeddedMetaJSON into a service name → spec map
// without touching mergedServices. Safe to call multiple times (sync.Once).
// parseEmbeddedServices parses the embedded meta (meta_data.json/default) and
// the built-in meta (meta_data_builtin.json) into a service name → spec map
// without touching mergedServices. Built-in services (e.g. hire) are included
// here too so the schema command and other embedded-spec consumers see them.
// Safe to call multiple times (sync.Once).
func parseEmbeddedServices() {
embeddedParseOnce.Do(func() {
embeddedServicesMap = make(map[string]map[string]interface{})
if len(embeddedMetaJSON) == 0 {
return
}
var wrapper struct {
Services []map[string]interface{} `json:"services"`
}
if err := json.Unmarshal(embeddedMetaJSON, &wrapper); err != nil {
return
}
for _, svc := range wrapper.Services {
name, _ := svc["name"].(string)
if name == "" {
for _, data := range [][]byte{embeddedMetaJSON, embeddedBuiltinJSON} {
if len(data) == 0 {
continue
}
embeddedServicesMap[name] = svc
var wrapper struct {
Services []map[string]interface{} `json:"services"`
}
if err := json.Unmarshal(data, &wrapper); err != nil {
continue
}
for _, svc := range wrapper.Services {
name, _ := svc["name"].(string)
if name == "" {
continue
}
embeddedServicesMap[name] = svc
}
}
embeddedServiceNames = make([]string, 0, len(embeddedServicesMap))
for name := range embeddedServicesMap {
Expand Down Expand Up @@ -122,11 +132,28 @@ func InitWithBrand(brand core.LarkBrand) {
triggerBackgroundRefresh()
}
}
// 2.5 Built-in services (hire) — always merged, after the remote
// decision so first-run sync-fetch logic is unaffected. The remote
// endpoint does not serve these, so they will not be overwritten.
loadBuiltinIntoMerged()
// 3. Build sorted project list
rebuildProjectList()
})
}

// loadBuiltinIntoMerged parses the embedded meta_data_builtin.json and overlays
// its services (e.g. hire) into mergedServices. No-op if not compiled in.
func loadBuiltinIntoMerged() {
if len(embeddedBuiltinJSON) == 0 {
return
}
var reg MergedRegistry
if err := json.Unmarshal(embeddedBuiltinJSON, &reg); err != nil {
return
}
overlayMergedServices(&reg)
}

// loadEmbeddedIntoMerged parses the embedded meta_data.json and populates
// mergedServices. No-op if meta_data.json is not compiled in.
func loadEmbeddedIntoMerged() {
Expand Down
6 changes: 6 additions & 0 deletions internal/registry/loader_embedded.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,10 @@ func init() {
} else {
embeddedMetaJSON = embeddedMetaDataDefaultJSON
}
// Built-in services (e.g. hire) that the remote api_definition endpoint
// does not serve. Always merged into the registry, independent of the
// remote-synced meta and the embedded fallback.
if data, err := metaFS.ReadFile("meta_data_builtin.json"); err == nil {
embeddedBuiltinJSON = data
}
}
Loading
Loading