Initial commit: img-infinite-canvas AI design workbench MVP
Moteva-style AI design workbench replica. Home prompt creates a project; the project page provides an infinite canvas with node drag, zoom/pan, a design chat panel, history replay, image asset upload, and project save/regenerate. - Backend: go-zero, DDD layering, sqlc/pgx, optional PostgreSQL; memory or Redis cache; asynq job queue; MinIO/S3/R2/OSS object storage; sky-valley/pi agent runtime adapter. - Frontend: Next.js App Router + Vite artifact build, TypeScript, i18n, shadcn/ui components, auth (OTP/Turnstile/Google/WeChat). - Deploy: Docker Compose and k3s manifests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
authmodule "img_infinite_canvas/internal/modules/auth"
|
||||
"img_infinite_canvas/internal/types"
|
||||
)
|
||||
|
||||
func toAPIAuthOptions(options authmodule.Options) *types.AuthOptionsResponse {
|
||||
methods := make([]types.AuthMethod, 0, len(options.Methods))
|
||||
for _, method := range options.Methods {
|
||||
methods = append(methods, types.AuthMethod{
|
||||
Id: method.ID,
|
||||
Label: method.Label,
|
||||
Provider: method.Provider,
|
||||
})
|
||||
}
|
||||
return &types.AuthOptionsResponse{
|
||||
Region: options.Region,
|
||||
Methods: methods,
|
||||
Turnstile: types.AuthTurnstileOptions{
|
||||
Enabled: options.Turnstile.Enabled,
|
||||
SiteKey: options.Turnstile.SiteKey,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func toAPIAuthCode(result authmodule.CodeResult) *types.AuthCodeResponse {
|
||||
var email *types.AuthEmailMessage
|
||||
if result.Email != nil {
|
||||
email = &types.AuthEmailMessage{
|
||||
FromName: result.Email.FromName,
|
||||
FromEmail: result.Email.FromEmail,
|
||||
ToEmail: result.Email.ToEmail,
|
||||
Subject: result.Email.Subject,
|
||||
Code: result.Email.Code,
|
||||
Text: result.Email.Text,
|
||||
Html: result.Email.HTML,
|
||||
}
|
||||
}
|
||||
return &types.AuthCodeResponse{
|
||||
Target: result.Target,
|
||||
ExpiresIn: result.ExpiresIn,
|
||||
DevCode: result.DevCode,
|
||||
Email: email,
|
||||
}
|
||||
}
|
||||
|
||||
func toAPIAuthSession(session authmodule.Session) *types.AuthSessionResponse {
|
||||
status := session.Status
|
||||
if status == "" {
|
||||
status = authmodule.SessionStatusAuthenticated
|
||||
}
|
||||
return &types.AuthSessionResponse{
|
||||
Status: status,
|
||||
User: types.AuthUser{
|
||||
Id: session.User.ID,
|
||||
Region: session.User.Region,
|
||||
Phone: session.User.Phone,
|
||||
CountryCode: session.User.CountryCode,
|
||||
Email: session.User.Email,
|
||||
Name: session.User.Name,
|
||||
AvatarUrl: session.User.AvatarURL,
|
||||
},
|
||||
AccessToken: session.AccessToken,
|
||||
ExpiresIn: session.ExpiresIn,
|
||||
RefreshToken: session.RefreshToken,
|
||||
RefreshExpiresIn: session.RefreshExpiresIn,
|
||||
BindingToken: session.BindingToken,
|
||||
BindingExpiresIn: session.BindingExpiresIn,
|
||||
}
|
||||
}
|
||||
|
||||
func toAPIAuthUser(user authmodule.User) types.AuthUser {
|
||||
return types.AuthUser{
|
||||
Id: user.ID,
|
||||
Region: user.Region,
|
||||
Phone: user.Phone,
|
||||
CountryCode: user.CountryCode,
|
||||
Email: user.Email,
|
||||
Name: user.Name,
|
||||
AvatarUrl: user.AvatarURL,
|
||||
}
|
||||
}
|
||||
|
||||
func toAPIAccountDevices(devices []authmodule.Device) []types.AccountDevice {
|
||||
items := make([]types.AccountDevice, 0, len(devices))
|
||||
for _, device := range devices {
|
||||
items = append(items, types.AccountDevice{
|
||||
Id: device.ID,
|
||||
Online: device.Online,
|
||||
Current: device.Current,
|
||||
DeviceType: device.DeviceType,
|
||||
System: device.System,
|
||||
Browser: device.Browser,
|
||||
Client: device.Client,
|
||||
LastSeenAt: device.LastSeenAt.UTC().Format("2006-01-02 15:04(UTC)"),
|
||||
})
|
||||
}
|
||||
return items
|
||||
}
|
||||
Reference in New Issue
Block a user