mirror of
https://github.com/larksuite/cli.git
synced 2026-07-03 22:24:31 +08:00
Adds the apps domain to lark-cli for managing Miaoda (妙搭) applications: 6 shortcuts covering the full lifecycle (+create / +update / +list / +access-scope-set / +access-scope-get / +html-publish). Aligned with the OAPI v2 design — app_type enum (currently HTML), string scope enum (All / Tenant / Range), cursor pagination, in-memory tar.gz multipart publish flow. Namespace registered at /open-apis/spark/v1/ with spark:app.* scopes. --------- Co-authored-by: wangjiangwen-gif <286006750+wangjiangwen-gif@users.noreply.github.com>
84 lines
2.6 KiB
Go
84 lines
2.6 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||
// SPDX-License-Identifier: MIT
|
||
|
||
package apps
|
||
|
||
import (
|
||
"bytes"
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"net/http"
|
||
|
||
larkcore "github.com/larksuite/oapi-sdk-go/v3/core"
|
||
|
||
"github.com/larksuite/cli/internal/output"
|
||
"github.com/larksuite/cli/internal/validate"
|
||
"github.com/larksuite/cli/shortcuts/common"
|
||
)
|
||
|
||
type htmlPublishResponse struct {
|
||
URL string
|
||
}
|
||
|
||
type appsHTMLPublishClient interface {
|
||
HTMLPublish(ctx context.Context, appID string, tarball *htmlPublishTarball) (*htmlPublishResponse, error)
|
||
}
|
||
|
||
type appsHTMLPublishAPI struct {
|
||
runtime *common.RuntimeContext
|
||
}
|
||
|
||
func (api appsHTMLPublishAPI) HTMLPublish(ctx context.Context, appID string, tarball *htmlPublishTarball) (*htmlPublishResponse, error) {
|
||
fd := larkcore.NewFormdata()
|
||
fd.AddFile("file", bytes.NewReader(tarball.Body))
|
||
|
||
apiResp, err := api.runtime.DoAPI(&larkcore.ApiReq{
|
||
HttpMethod: http.MethodPost,
|
||
ApiPath: fmt.Sprintf("%s/apps/%s/upload_and_release_html_code", apiBasePath, validate.EncodePathSegment(appID)),
|
||
Body: fd,
|
||
}, larkcore.WithFileUpload())
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return parseHTMLPublishResponse(apiResp.RawBody)
|
||
}
|
||
|
||
func parseHTMLPublishResponse(raw []byte) (*htmlPublishResponse, error) {
|
||
var envelope struct {
|
||
Code int `json:"code"`
|
||
Msg string `json:"msg"`
|
||
Data struct {
|
||
URL string `json:"url"`
|
||
} `json:"data"`
|
||
}
|
||
if err := json.Unmarshal(raw, &envelope); err != nil {
|
||
return nil, fmt.Errorf("decode html-publish response: %w", err)
|
||
}
|
||
if envelope.Code != 0 {
|
||
return nil, output.ErrWithHint(output.ExitAPI, "api_error",
|
||
fmt.Sprintf("html-publish failed (code=%d): %s", envelope.Code, envelope.Msg),
|
||
buildHTMLPublishFailureHint(envelope.Code))
|
||
}
|
||
return &htmlPublishResponse{URL: envelope.Data.URL}, nil
|
||
}
|
||
|
||
// OAPI business error codes returned by the Miaoda
|
||
// /apps/{id}/upload_and_release_html_code endpoint. Owned by the backend
|
||
// service; update when new codes are documented in the OAPI spec.
|
||
const (
|
||
errCodeBuildFailed = 90001 // tar.gz uploaded but server-side build failed
|
||
errCodeAppNotFound = 90002 // app_id unknown or caller lacks permission
|
||
)
|
||
|
||
func buildHTMLPublishFailureHint(code int) string {
|
||
switch code {
|
||
case errCodeBuildFailed:
|
||
return "构建失败:用 `lark-cli apps +html-publish --app-id <your-app-id> --path <path> --dry-run` 检查打包文件清单"
|
||
case errCodeAppNotFound:
|
||
return "应用不存在或无权访问;请用户确认 app_id(从妙搭应用链接 https://miaoda.feishu.cn/app/app_xxx 的 /app/ 后面提取,或直接给 app_xxx 字符串)"
|
||
default:
|
||
return ""
|
||
}
|
||
}
|