1
27
internal/auth/client.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
RegisterUser(ctx context.Context, request RegisterUserRequest) (*RegisterUserResponse, error)
|
||||
LoginUser(ctx context.Context, request LoginUserRequest) (*LoginUserResponse, error)
|
||||
LogoutUser(ctx context.Context, request LogoutUserRequest) error
|
||||
GetNewAccessToken(ctx context.Context, request GetNewAccessTokenRequest) (*GetNewAccessTokenResponse, error)
|
||||
GetUserEmailVerificationToken(ctx context.Context, uid string) (*GetUserTokenResponse, error)
|
||||
CheckTokenIsValid(ctx context.Context, token string) (bool, error)
|
||||
GetPermissionsByUsersId(ctx context.Context, id string) (*GetPermissionsByUsersIdResponse, error)
|
||||
CheckPermissions(ctx context.Context, required CheckPermissionsRequest) (bool, error)
|
||||
GetUserInfo(ctx context.Context, id string) (*UserInfo, error)
|
||||
VerifyEmail(ctx context.Context, userID string, token string) error
|
||||
GetEmailVerificationStatus(ctx context.Context, userID string) (*GetEmailVerificationResponse, error)
|
||||
ResetPassword(ctx context.Context, request ResetPasswordRequest) error
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
AuthServerAddr string
|
||||
Realm string
|
||||
ClientId string
|
||||
ClientSecret string
|
||||
}
|
||||
104
internal/auth/domain.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package auth
|
||||
|
||||
type (
|
||||
User struct {
|
||||
Email string
|
||||
Password string
|
||||
FirstName string
|
||||
SecondName string
|
||||
Patronymic *string
|
||||
Number string
|
||||
Permissions map[string]string
|
||||
}
|
||||
|
||||
RegisterUserRequest struct {
|
||||
User User
|
||||
UserType int32
|
||||
}
|
||||
|
||||
RegisterUserResponse struct {
|
||||
UserId string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
LoginUserRequest struct {
|
||||
Email string
|
||||
Password string
|
||||
}
|
||||
|
||||
LoginUserResponse struct {
|
||||
UserId string `json:"user_id"`
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
GetUserTokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
LogoutUserRequest struct {
|
||||
RefreshToken string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
GetNewAccessTokenRequest struct {
|
||||
RefreshToken string
|
||||
}
|
||||
|
||||
GetNewAccessTokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
UserInfoFromToken struct {
|
||||
UserId string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
GetPermissionsByUsersIdResponse struct {
|
||||
Balance string
|
||||
Company string
|
||||
Employees string
|
||||
Profile string
|
||||
Submissions string
|
||||
Vacancies string
|
||||
}
|
||||
)
|
||||
type (
|
||||
CheckPermissionsRequest struct {
|
||||
UserId string
|
||||
RequiredPermission string
|
||||
RequiredPermissionLevel string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
ResetPasswordRequest struct {
|
||||
Email string
|
||||
NewPassword string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
UserInfo struct {
|
||||
Email string
|
||||
FirstName string
|
||||
SecondName string
|
||||
Patronymic *string
|
||||
Permissions map[string]string
|
||||
UserType int32
|
||||
}
|
||||
)
|
||||
|
||||
type GetEmailVerificationResponse struct {
|
||||
EmailVerified bool `json:"email_verified"`
|
||||
}
|
||||
390
internal/auth/keycloak/auth.go
Normal file
@@ -0,0 +1,390 @@
|
||||
package keycloak
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/auth"
|
||||
"github.com/Nerzal/gocloak/v13"
|
||||
)
|
||||
|
||||
func (k *Client) RegisterUser(ctx context.Context, request auth.RegisterUserRequest) (*auth.RegisterUserResponse, error) {
|
||||
attrs := make(map[string][]string)
|
||||
|
||||
if request.User.Patronymic != nil {
|
||||
attrs[PatronymicAttr] = []string{*request.User.Patronymic}
|
||||
}
|
||||
|
||||
for key, value := range request.User.Permissions {
|
||||
attrs[key] = []string{value}
|
||||
}
|
||||
|
||||
for _, perm := range permissionsSlice {
|
||||
if _, ok := attrs[perm]; !ok {
|
||||
return nil, errors.Join(ErrBadRequest, ErrMissingPermission)
|
||||
}
|
||||
}
|
||||
|
||||
client, err := k.client.LoginClient(ctx, k.clientId, k.clientSecret, k.realm)
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
userGroup, err := k.getUserGroupByType(request.UserType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
emailVerified := false
|
||||
if k.env != "production" {
|
||||
emailVerified = true
|
||||
}
|
||||
|
||||
userId, err := k.client.CreateUser(
|
||||
ctx,
|
||||
client.AccessToken,
|
||||
k.realm,
|
||||
gocloak.User{
|
||||
Email: gocloak.StringP(request.User.Email),
|
||||
EmailVerified: &emailVerified,
|
||||
FirstName: gocloak.StringP(request.User.FirstName),
|
||||
LastName: gocloak.StringP(request.User.SecondName),
|
||||
Groups: &[]string{userGroup},
|
||||
Enabled: gocloak.BoolP(true),
|
||||
Attributes: &attrs,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
if err = k.client.SetPassword(
|
||||
ctx, client.AccessToken,
|
||||
userId, k.realm,
|
||||
request.User.Password, false,
|
||||
); err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
return &auth.RegisterUserResponse{
|
||||
UserId: userId,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *Client) getUserGroupByType(userType int32) (string, error) {
|
||||
switch userType {
|
||||
case UserAgentType:
|
||||
return UserGroupAgents, nil
|
||||
case UserDistributorType:
|
||||
return UserGroupDistributor, nil
|
||||
default:
|
||||
return "", ErrUnknownUserType
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Client) LoginUser(ctx context.Context, request auth.LoginUserRequest) (*auth.LoginUserResponse, error) {
|
||||
token, err := k.client.Login(ctx, k.clientId, k.clientSecret, k.realm, request.Email, request.Password)
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
userInfo, err := k.jwtManager.GetUserInfoFromToken(token.AccessToken)
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
return &auth.LoginUserResponse{
|
||||
UserId: userInfo.UserId,
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *Client) GetNewAccessToken(ctx context.Context, request auth.GetNewAccessTokenRequest) (*auth.GetNewAccessTokenResponse, error) {
|
||||
token, err := k.client.RefreshToken(ctx, request.RefreshToken, k.clientId, k.clientSecret, k.realm)
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
return &auth.GetNewAccessTokenResponse{
|
||||
AccessToken: token.AccessToken,
|
||||
RefreshToken: token.RefreshToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *Client) CheckTokenIsValid(ctx context.Context, token string) (bool, error) {
|
||||
resp, err := k.client.RetrospectToken(ctx, token, k.clientId, k.clientSecret, k.realm)
|
||||
if err != nil {
|
||||
return false, k.handleError(err)
|
||||
}
|
||||
|
||||
if resp.Active == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return *resp.Active, nil
|
||||
}
|
||||
|
||||
func (k *Client) LogoutUser(ctx context.Context, request auth.LogoutUserRequest) error {
|
||||
if err := k.client.Logout(ctx, k.clientId, k.clientSecret, k.realm, request.RefreshToken); err != nil {
|
||||
return k.handleError(err)
|
||||
}
|
||||
|
||||
if err := k.client.RevokeToken(ctx, k.realm, k.clientId, k.clientSecret, request.RefreshToken); err != nil {
|
||||
return k.handleError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *Client) GetUserInfo(ctx context.Context, id string) (*auth.UserInfo, error) {
|
||||
client, err := k.client.LoginClient(ctx, k.clientId, k.clientSecret, k.realm)
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
user, err := k.client.GetUserByID(ctx, client.AccessToken, k.realm, id)
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
if user.Attributes == nil {
|
||||
return nil, ErrNoAttributes
|
||||
}
|
||||
|
||||
groups, err := k.client.GetUserGroups(ctx, client.AccessToken, k.realm, id, gocloak.GetGroupsParams{})
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
if len(groups) == 0 {
|
||||
return nil, ErrUnknownUserType
|
||||
}
|
||||
|
||||
if groups[0].Name == nil {
|
||||
return nil, ErrUnknownUserType
|
||||
}
|
||||
|
||||
userType, err := k.getUserTypeByUserGroup(*groups[0].Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &auth.UserInfo{
|
||||
Email: *user.Email,
|
||||
FirstName: *user.FirstName,
|
||||
SecondName: *user.LastName,
|
||||
Patronymic: k.getUserPatronymicFromAttributes(*user.Attributes),
|
||||
Permissions: k.getUserPermissionsFromAttributes(*user.Attributes),
|
||||
UserType: userType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *Client) getUserPatronymicFromAttributes(attr attributes) *string {
|
||||
item, ok := attr[PatronymicAttr]
|
||||
if !ok || len(item) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &item[0]
|
||||
}
|
||||
|
||||
func (k *Client) getUserPermissionsFromAttributes(attr attributes) permissions {
|
||||
resp := make(map[string]string)
|
||||
|
||||
for _, permission := range permissionsSlice {
|
||||
if item, ok := attr[permission]; ok {
|
||||
if len(item) != 0 {
|
||||
resp[permission] = item[0]
|
||||
} else {
|
||||
resp[permission] = "" // todo: подумать над тем как правильно делать в таких ситуациях
|
||||
}
|
||||
} else {
|
||||
resp[permission] = "" // todo: подумать над тем как правильно делать в таких ситуациях
|
||||
}
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
func (k *Client) getUserTypeByUserGroup(attr string) (int32, error) {
|
||||
switch attr {
|
||||
case UserGroupAgents:
|
||||
return UserAgentType, nil
|
||||
case UserGroupDistributor:
|
||||
return UserDistributorType, nil
|
||||
default:
|
||||
return -1, ErrUnknownUserType
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Client) GetPermissionsByUsersId(ctx context.Context, id string) (*auth.GetPermissionsByUsersIdResponse, error) {
|
||||
userInfo, err := k.GetUserInfo(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &auth.GetPermissionsByUsersIdResponse{
|
||||
Balance: userInfo.Permissions[PermissionBalance],
|
||||
Company: userInfo.Permissions[PermissionCompany],
|
||||
Employees: userInfo.Permissions[PermissionEmployees],
|
||||
Profile: userInfo.Permissions[PermissionProfile],
|
||||
Submissions: userInfo.Permissions[PermissionSubmissions],
|
||||
Vacancies: userInfo.Permissions[PermissionVacancies],
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *Client) CheckPermissions(ctx context.Context, request auth.CheckPermissionsRequest) (bool, error) {
|
||||
userInfo, err := k.GetUserInfo(ctx, request.UserId)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if userInfo.Permissions == nil {
|
||||
return false, ErrInternal
|
||||
}
|
||||
|
||||
if val, ok := userInfo.Permissions[request.RequiredPermission]; ok {
|
||||
return k.getPermissionLevel(val) >= k.getPermissionLevel(request.RequiredPermissionLevel), nil
|
||||
}
|
||||
|
||||
return false, ErrInternal
|
||||
}
|
||||
|
||||
func (k *Client) getPermissionLevel(permission string) int8 {
|
||||
switch permission {
|
||||
case PermissionLevelCanEdit:
|
||||
return 2
|
||||
case PermissionLevelCanView:
|
||||
return 1
|
||||
case PermissionLevelNoPermission:
|
||||
return 0
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Client) VerifyEmail(ctx context.Context, userID string, token string) error {
|
||||
if err := k.jwtManager.VerifyEmailToken(token, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get admin token
|
||||
adminToken, err := k.client.LoginClient(ctx, k.clientId, k.clientSecret, k.realm)
|
||||
if err != nil {
|
||||
return k.handleError(err)
|
||||
}
|
||||
|
||||
// Get user
|
||||
user, err := k.client.GetUserByID(ctx, adminToken.AccessToken, k.realm, userID)
|
||||
if err != nil {
|
||||
return k.handleError(err)
|
||||
}
|
||||
|
||||
// Set email as verified
|
||||
user.EmailVerified = gocloak.BoolP(true)
|
||||
|
||||
// Update user
|
||||
if err := k.client.UpdateUser(ctx, adminToken.AccessToken, k.realm, *user); err != nil {
|
||||
return k.handleError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *Client) GetEmailVerificationStatus(ctx context.Context, userID string) (*auth.GetEmailVerificationResponse, error) {
|
||||
// Get admin token
|
||||
adminToken, err := k.client.LoginClient(ctx, k.clientId, k.clientSecret, k.realm)
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
// Get user
|
||||
user, err := k.client.GetUserByID(ctx, adminToken.AccessToken, k.realm, userID)
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
// Check if email is verified
|
||||
verified := false
|
||||
if user.EmailVerified != nil {
|
||||
verified = *user.EmailVerified
|
||||
}
|
||||
|
||||
return &auth.GetEmailVerificationResponse{
|
||||
EmailVerified: verified,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *Client) GetUserEmailVerificationToken(ctx context.Context, uid string) (*auth.GetUserTokenResponse, error) {
|
||||
// Получение токена администратора
|
||||
adminToken, err := k.client.LoginClient(ctx, k.clientId, k.clientSecret, k.realm)
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
// Получаем пользователя, чтобы убедиться в его существовании
|
||||
_, err = k.client.GetUserByID(ctx, adminToken.AccessToken, k.realm, uid)
|
||||
if err != nil {
|
||||
return nil, k.handleError(err)
|
||||
}
|
||||
|
||||
// Создаём кастомный JWT-токен для верификации email сроком на 24 часа
|
||||
claims := jwt.MapClaims{
|
||||
"sub": uid, // Subject (user ID)
|
||||
"iat": time.Now().Unix(), // Issued at
|
||||
"exp": time.Now().Add(24 * time.Hour).Unix(), // Expires in 24 hours
|
||||
"purpose": "email_verification", // Custom claim to identify purpose
|
||||
"iss": "molva-api-gateway", // Issuer
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
|
||||
// Используем клиентский секрет как ключ подписи
|
||||
signedToken, err := token.SignedString([]byte(k.clientSecret))
|
||||
if err != nil {
|
||||
return nil, ErrInternal
|
||||
}
|
||||
|
||||
return &auth.GetUserTokenResponse{
|
||||
AccessToken: signedToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *Client) ResetPassword(ctx context.Context, request auth.ResetPasswordRequest) error {
|
||||
token, err := k.client.LoginClient(ctx, k.clientId, k.clientSecret, k.realm)
|
||||
if err != nil {
|
||||
return k.handleError(err)
|
||||
}
|
||||
|
||||
user, err := k.client.GetUsers(
|
||||
ctx,
|
||||
token.AccessToken,
|
||||
k.realm,
|
||||
gocloak.GetUsersParams{
|
||||
Username: gocloak.StringP(request.Email),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return k.handleError(err)
|
||||
}
|
||||
|
||||
if len(user) == 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
|
||||
if err := k.client.SetPassword(
|
||||
ctx,
|
||||
token.AccessToken,
|
||||
*user[0].ID,
|
||||
k.realm,
|
||||
request.NewPassword,
|
||||
false,
|
||||
); err != nil {
|
||||
return k.handleError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
15
internal/auth/keycloak/client.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package keycloak
|
||||
|
||||
import (
|
||||
"github.com/Nerzal/gocloak/v13"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
client *gocloak.GoCloak
|
||||
jwtManager TokenManager
|
||||
|
||||
env string
|
||||
realm string
|
||||
clientId string
|
||||
clientSecret string
|
||||
}
|
||||
38
internal/auth/keycloak/constants.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package keycloak
|
||||
|
||||
const (
|
||||
PatronymicAttr = "patronymic"
|
||||
|
||||
PermissionLevelCanEdit = "can_edit"
|
||||
PermissionLevelCanView = "can_view"
|
||||
PermissionLevelNoPermission = "no_permission"
|
||||
|
||||
UserGroupAgents = "agents"
|
||||
UserGroupDistributor = "distributors"
|
||||
|
||||
UserAgentType = 0
|
||||
UserDistributorType = 1
|
||||
|
||||
PermissionBalance = "balance"
|
||||
PermissionCompany = "company"
|
||||
PermissionEmployees = "employees"
|
||||
PermissionProfile = "profile"
|
||||
PermissionSubmissions = "submissions"
|
||||
PermissionVacancies = "vacancies"
|
||||
)
|
||||
|
||||
var (
|
||||
permissionsSlice = []string{
|
||||
PermissionBalance,
|
||||
PermissionCompany,
|
||||
PermissionEmployees,
|
||||
PermissionProfile,
|
||||
PermissionSubmissions,
|
||||
PermissionVacancies,
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
attributes map[string][]string
|
||||
permissions map[string]string
|
||||
)
|
||||
16
internal/auth/keycloak/errors.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package keycloak
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrInvalidToken = errors.New("invalid token")
|
||||
ErrInternal = errors.New("internal error")
|
||||
ErrRealmClientNotFound = errors.New("realm client not found")
|
||||
ErrRealmClientUnauthorized = errors.New("realm client unauthorized")
|
||||
ErrUnknownUserType = errors.New("unknown user type")
|
||||
ErrNoAttributes = errors.New("no attributes")
|
||||
ErrAlreadyExists = errors.New("user already exists")
|
||||
ErrBadRequest = errors.New("bad request")
|
||||
ErrNotFound = errors.New("user not found")
|
||||
ErrMissingPermission = errors.New("missing one or more permissions")
|
||||
)
|
||||
51
internal/auth/keycloak/interface.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package keycloak
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/Nerzal/gocloak/v13"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Env string
|
||||
AuthServerAddr string
|
||||
Realm string
|
||||
ClientId string
|
||||
ClientSecret string
|
||||
}
|
||||
|
||||
func New(c *Config) (*Client, error) {
|
||||
cli := &Client{
|
||||
client: gocloak.NewClient(c.AuthServerAddr),
|
||||
jwtManager: NewJWTManager(),
|
||||
|
||||
env: c.Env,
|
||||
realm: c.Realm,
|
||||
clientId: c.ClientId,
|
||||
clientSecret: c.ClientSecret,
|
||||
}
|
||||
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func (k *Client) handleError(err error) error {
|
||||
var apiErr *gocloak.APIError
|
||||
|
||||
if !errors.As(err, &apiErr) {
|
||||
return ErrInternal
|
||||
}
|
||||
|
||||
switch apiErr.Code {
|
||||
case http.StatusNotFound:
|
||||
return ErrRealmClientNotFound
|
||||
case http.StatusUnauthorized:
|
||||
return ErrRealmClientUnauthorized
|
||||
case http.StatusConflict:
|
||||
return ErrAlreadyExists
|
||||
case http.StatusBadRequest:
|
||||
return ErrBadRequest
|
||||
default:
|
||||
return ErrInternal
|
||||
}
|
||||
}
|
||||
76
internal/auth/keycloak/jwt.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package keycloak
|
||||
|
||||
import (
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/auth"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TokenManager interface {
|
||||
GetUserInfoFromToken(token string) (*auth.UserInfoFromToken, error)
|
||||
VerifyEmailToken(token string, expectedUserID string) error
|
||||
}
|
||||
|
||||
type tokenManager struct {
|
||||
parser *jwt.Parser
|
||||
}
|
||||
|
||||
func NewJWTManager() TokenManager {
|
||||
return &tokenManager{
|
||||
parser: jwt.NewParser(),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tokenManager) GetUserInfoFromToken(token string) (*auth.UserInfoFromToken, error) {
|
||||
userToken, _, err := t.parser.ParseUnverified(token, jwt.MapClaims{})
|
||||
if err != nil {
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
if claims, ok := userToken.Claims.(jwt.MapClaims); ok {
|
||||
resp := auth.UserInfoFromToken{}
|
||||
|
||||
resp.UserId, ok = claims["sub"].(string)
|
||||
if !ok {
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
return nil, ErrInvalidToken
|
||||
}
|
||||
|
||||
func (t *tokenManager) VerifyEmailToken(token string, expectedUserID string) error {
|
||||
// Parse token without verification (we'll verify signature manually)
|
||||
parsedToken, _, err := t.parser.ParseUnverified(token, jwt.MapClaims{})
|
||||
if err != nil {
|
||||
return ErrInvalidToken
|
||||
}
|
||||
|
||||
// Extract claims
|
||||
claims, ok := parsedToken.Claims.(jwt.MapClaims)
|
||||
if !ok {
|
||||
return ErrInvalidToken
|
||||
}
|
||||
|
||||
// Check if token is for email verification
|
||||
purpose, ok := claims["purpose"].(string)
|
||||
if !ok || purpose != "email_verification" {
|
||||
return ErrInvalidToken
|
||||
}
|
||||
|
||||
// Check if subject matches expected user ID
|
||||
sub, ok := claims["sub"].(string)
|
||||
if !ok || sub != expectedUserID {
|
||||
return ErrInvalidToken
|
||||
}
|
||||
|
||||
// Check expiration
|
||||
exp, ok := claims["exp"].(float64)
|
||||
if !ok || float64(time.Now().Unix()) > exp {
|
||||
return ErrInvalidToken
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
257
internal/broker/rmq.go
Normal file
@@ -0,0 +1,257 @@
|
||||
package broker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/config"
|
||||
requestmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model"
|
||||
"github.com/google/uuid"
|
||||
amqp "github.com/rabbitmq/amqp091-go"
|
||||
)
|
||||
|
||||
var conn *amqp.Connection
|
||||
|
||||
var (
|
||||
NotificationQueue string
|
||||
)
|
||||
|
||||
type Broker interface {
|
||||
Connect() error
|
||||
Disconnect() error
|
||||
}
|
||||
|
||||
type RabbitMQBroker struct {
|
||||
cfg *config.Broker
|
||||
}
|
||||
|
||||
func NewRabbitMQBroker(cfg *config.Broker) *RabbitMQBroker {
|
||||
NotificationQueue = cfg.NotificationsQueueName
|
||||
|
||||
return &RabbitMQBroker{
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *RabbitMQBroker) Connect() error {
|
||||
var err error
|
||||
|
||||
rabbitConn := fmt.Sprintf(
|
||||
"amqp://%s:%s@%s:%d",
|
||||
r.cfg.UserName,
|
||||
r.cfg.Password,
|
||||
r.cfg.Host,
|
||||
r.cfg.Port,
|
||||
)
|
||||
|
||||
conn, err = amqp.Dial(rabbitConn)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *RabbitMQBroker) Disconnect() error {
|
||||
return conn.Close()
|
||||
}
|
||||
|
||||
func produceMessage(qName, replyToQName, corrId string, message []byte, headers amqp.Table) (err error) {
|
||||
ch, err := conn.Channel()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func(ch *amqp.Channel) {
|
||||
if errClose := ch.Close(); errClose != nil {
|
||||
err = errors.Join(err, errClose)
|
||||
}
|
||||
}(ch)
|
||||
|
||||
q, err := ch.QueueDeclare(
|
||||
qName, // name
|
||||
true, // durable
|
||||
false, // delete when unused
|
||||
false, // exclusive
|
||||
false, // no-wait
|
||||
nil, // arguments
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), constants.DefaultContextTimeout)
|
||||
defer cancel()
|
||||
|
||||
err = ch.PublishWithContext(ctx,
|
||||
"", // exchange
|
||||
q.Name, // routing key
|
||||
false, // mandatory
|
||||
false, // immediate
|
||||
amqp.Publishing{
|
||||
DeliveryMode: amqp.Persistent,
|
||||
Type: headers["command"].(string),
|
||||
ReplyTo: replyToQName,
|
||||
CorrelationId: corrId,
|
||||
Body: message,
|
||||
Headers: headers,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func consumeMessage(qName string, corrId string) (resp []byte, err error) {
|
||||
ch, err := conn.Channel()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer func(ch *amqp.Channel) {
|
||||
if errClose := ch.Close(); errClose != nil {
|
||||
err = errors.Join(err, errClose)
|
||||
}
|
||||
}(ch)
|
||||
|
||||
if _, err = ch.QueueDeclare(
|
||||
qName, // name
|
||||
true, // durable
|
||||
true, // delete when unused
|
||||
false, // exclusive
|
||||
false, // no-wait
|
||||
nil, // arguments
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
messages, err := ch.Consume(
|
||||
qName, // queue
|
||||
"", // consumer
|
||||
false, // auto-ack
|
||||
false, // exclusive
|
||||
false, // no-local
|
||||
false, // no-wait
|
||||
nil, // args
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := <-messages
|
||||
//todo: Поправить на проверку correlationId
|
||||
// if d.CorrelationId == corrId {
|
||||
// return nil, fmt.Errorf("invalid correlation ID %s", d.CorrelationId)
|
||||
// }
|
||||
|
||||
if err = response.Ack(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response.Body, nil
|
||||
}
|
||||
|
||||
func ProcessRequest(qName, replyToQName, corrId string, headers amqp.Table, message []byte, log *slog.Logger) ([]byte, error) {
|
||||
log.Info("produce request to: ",
|
||||
slog.String("qName", qName),
|
||||
slog.String("replyToQName", replyToQName),
|
||||
slog.String("command", headers["command"].(string)),
|
||||
slog.String("corrId", corrId),
|
||||
)
|
||||
|
||||
if err := produceMessage(qName, replyToQName, corrId, message, headers); err != nil {
|
||||
log.Error("got some error while producing message: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("corrId", corrId))
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Info("consume response from: ",
|
||||
slog.String("qName", qName),
|
||||
slog.String("replyToQName", replyToQName),
|
||||
slog.String("command", headers["command"].(string)),
|
||||
slog.String("corrId", corrId),
|
||||
)
|
||||
|
||||
body, err := consumeMessage(replyToQName, corrId)
|
||||
if err != nil {
|
||||
log.Error("got some error while consuming message: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("corrId", corrId))
|
||||
|
||||
return body, err
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
func BuildAndProcessRequest(qName string, headers requestmodel.Header, message []byte, log *slog.Logger) ([]byte, error) {
|
||||
queueUuid := uuid.New().String()
|
||||
|
||||
resp, err := ProcessRequest(
|
||||
qName,
|
||||
queueUuid,
|
||||
"0",
|
||||
headers.ToTable(),
|
||||
message,
|
||||
log,
|
||||
)
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func SendNotification(qName, messageType string, message []byte, log *slog.Logger) error {
|
||||
ch, err := conn.Channel()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func(ch *amqp.Channel) {
|
||||
if errClose := ch.Close(); errClose != nil {
|
||||
err = errors.Join(err, errClose)
|
||||
}
|
||||
}(ch)
|
||||
|
||||
q, err := ch.QueueDeclare(
|
||||
qName, // name
|
||||
true, // durable
|
||||
false, // delete when unused
|
||||
false, // exclusive
|
||||
false, // no-wait
|
||||
nil, // arguments
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("error while sending notification message",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("qName", qName))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), constants.DefaultContextTimeout)
|
||||
defer cancel()
|
||||
|
||||
err = ch.PublishWithContext(ctx,
|
||||
"", // exchange
|
||||
q.Name, // routing key
|
||||
false, // mandatory
|
||||
false, // immediate
|
||||
amqp.Publishing{
|
||||
Type: messageType,
|
||||
Body: message,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("error while sending notification message",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("qName", qName))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
16
internal/cache/client.go
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package cache
|
||||
|
||||
import "fmt"
|
||||
|
||||
func New(c Config, t Type) (Client, error) {
|
||||
switch t {
|
||||
case ValkeyCacheType:
|
||||
return newValKeyCache(c)
|
||||
default:
|
||||
return nil, ErrUnknownCacheType
|
||||
}
|
||||
}
|
||||
|
||||
func getKey(k string, t ValueType) string {
|
||||
return fmt.Sprintf("%s:%s", t, k)
|
||||
}
|
||||
16
internal/cache/errors.go
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
package cache
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrUnknownCacheType = errors.New("unknown cache type")
|
||||
ErrInvalidConfig = errors.New("invalid config")
|
||||
ErrConnect = errors.New("connecting to server")
|
||||
ErrTlsConfig = errors.New("tls config")
|
||||
ErrInvalidInstance = errors.New("check instance failed")
|
||||
ErrKeyNotFound = errors.New("key not found")
|
||||
ErrKeyExists = errors.New("key already exists")
|
||||
ErrGet = errors.New("failed to get value")
|
||||
ErrSet = errors.New("failed to set value")
|
||||
ErrDel = errors.New("failed to delete value")
|
||||
)
|
||||
53
internal/cache/types.go
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
// Set добавляет в кеш под ключем key значение value
|
||||
//
|
||||
// Если такого ключа с таким типом значения нет,
|
||||
// то возвращает ошибку ErrKeyExists
|
||||
Set(ctx context.Context, key string, valueType ValueType, value any, expiration time.Duration) error
|
||||
|
||||
// Del удаляет значение по ключу key и указанному valueType
|
||||
//
|
||||
// Если такого ключа с таким типом значения нет,
|
||||
// то возвращает ошибку ErrKeyNotFound
|
||||
Del(ctx context.Context, key string, valueType ValueType) error
|
||||
|
||||
// Get возвращает значение по ключу key и valueType
|
||||
//
|
||||
// Если такого ключа с таким типом значения нет,
|
||||
// то возвращает ошибку ErrKeyNotFound
|
||||
//
|
||||
// В случае, если получаемое значение не является строкой,
|
||||
// необходимо воспользоваться соответсвующим методом под
|
||||
// этот тип данных
|
||||
Get(ctx context.Context, key string, valueType ValueType) (string, error)
|
||||
|
||||
// TODO: По необходимости расширить необходимыми методами
|
||||
}
|
||||
|
||||
type (
|
||||
Type uint
|
||||
ValueType string
|
||||
Config any
|
||||
)
|
||||
|
||||
const (
|
||||
ValkeyCacheType Type = iota
|
||||
)
|
||||
|
||||
const (
|
||||
LogoValueType ValueType = "value_logo_type"
|
||||
DocumentsValueType ValueType = "value_documents_type"
|
||||
|
||||
PswResetOTPValueType ValueType = "value_otp_type"
|
||||
PswResetTokenValueType ValueType = "value_token_type"
|
||||
|
||||
IntegrationCompanyValueType ValueType = "integration:company"
|
||||
IntegrationVacancyValueType ValueType = "integration:vacancy"
|
||||
)
|
||||
143
internal/cache/valkey.go
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/go-redis/redis/v7"
|
||||
)
|
||||
|
||||
type ValKeyCacheConfig struct {
|
||||
Addrs []string
|
||||
Password string
|
||||
ReadOnly bool
|
||||
DialTimeout time.Duration
|
||||
PoolSize int
|
||||
DefaultTTL time.Duration
|
||||
RootCaFilePath string
|
||||
}
|
||||
|
||||
type valkeyClient interface {
|
||||
Set(key string, value any, expiration time.Duration) *redis.StatusCmd
|
||||
Get(key string) *redis.StringCmd
|
||||
Del(keys ...string) *redis.IntCmd
|
||||
Exists(keys ...string) *redis.IntCmd
|
||||
Ping() *redis.StatusCmd
|
||||
}
|
||||
|
||||
type valKeyCache struct {
|
||||
config ValKeyCacheConfig
|
||||
client valkeyClient
|
||||
}
|
||||
|
||||
func newValKeyCache(c Config) (*valKeyCache, error) {
|
||||
cfg, ok := c.(ValKeyCacheConfig)
|
||||
if !ok {
|
||||
return nil, ErrInvalidConfig
|
||||
}
|
||||
|
||||
caCert, err := os.ReadFile(cfg.RootCaFilePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %s", ErrTlsConfig, err.Error())
|
||||
}
|
||||
|
||||
caCertPool := x509.NewCertPool()
|
||||
|
||||
if ok := caCertPool.AppendCertsFromPEM(caCert); !ok {
|
||||
return nil, fmt.Errorf("%w: %s", ErrTlsConfig, "failed to append CA cert to pool")
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
RootCAs: caCertPool,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
|
||||
client := redis.NewUniversalClient(&redis.UniversalOptions{
|
||||
Addrs: cfg.Addrs,
|
||||
Password: cfg.Password,
|
||||
ReadOnly: cfg.ReadOnly,
|
||||
DialTimeout: cfg.DialTimeout,
|
||||
PoolSize: cfg.PoolSize,
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
|
||||
if err := client.Ping().Err(); err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrConnect, err)
|
||||
}
|
||||
|
||||
return &valKeyCache{
|
||||
config: cfg,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *valKeyCache) Get(ctx context.Context, key string, valueType ValueType) (string, error) {
|
||||
if err := c.checkInstance(); err != nil {
|
||||
return "", fmt.Errorf("%w: %v", ErrGet, err)
|
||||
}
|
||||
|
||||
val, err := c.client.Get(getKey(key, valueType)).Result()
|
||||
if err == redis.Nil {
|
||||
return "", ErrKeyNotFound
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%w: %v", ErrGet, err)
|
||||
}
|
||||
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func (c *valKeyCache) Set(ctx context.Context, key string, valueType ValueType, value any, expiration time.Duration) error {
|
||||
if err := c.checkInstance(); err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrSet, err)
|
||||
}
|
||||
|
||||
key = getKey(key, valueType)
|
||||
|
||||
if exists, err := c.client.Exists(key).Result(); err != nil || exists == 1 {
|
||||
if exists == 1 {
|
||||
return ErrKeyExists
|
||||
}
|
||||
|
||||
return fmt.Errorf("%w: %v", ErrSet, err)
|
||||
}
|
||||
|
||||
if err := c.client.Set(key, value, expiration).Err(); err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrSet, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *valKeyCache) Del(ctx context.Context, key string, valueType ValueType) error {
|
||||
if err := c.checkInstance(); err != nil {
|
||||
return fmt.Errorf("%w: %v", ErrDel, err.Error())
|
||||
}
|
||||
|
||||
if res, err := c.client.Del(getKey(key, valueType)).Result(); err != nil || res == 0 {
|
||||
if res == 0 {
|
||||
return ErrKeyNotFound
|
||||
}
|
||||
|
||||
return fmt.Errorf("%w: %s", ErrDel, err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *valKeyCache) checkInstance() error {
|
||||
if c == nil {
|
||||
return ErrInvalidInstance
|
||||
}
|
||||
|
||||
if s := c.client.Ping(); s.Err() != nil {
|
||||
return fmt.Errorf("%w: %v", ErrInvalidInstance, s.Err().Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
53
internal/config/config.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/ilyakaznacheev/cleanenv"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInternal = errors.New("can not load config")
|
||||
ErrMarshaling = errors.New("can not marshal config path")
|
||||
)
|
||||
|
||||
func MustLoad(version, commit, date string) *Config {
|
||||
cfg, err := loadConfig()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cfg.Build.Version = version
|
||||
cfg.Build.Commit = commit
|
||||
cfg.Build.Date = date
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func loadConfig() (*Config, error) {
|
||||
if _, err := os.Stat(ConfigBasePath); os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("no config file found")
|
||||
}
|
||||
|
||||
var localConfig LocalDeploy
|
||||
|
||||
if err := cleanenv.ReadConfig(ConfigBasePath, &localConfig); err != nil {
|
||||
return nil, fmt.Errorf("error reading local config: %w", err)
|
||||
}
|
||||
|
||||
for _, env := range localConfig.Deploy.Env {
|
||||
if err := os.Setenv(env.Name, env.Value); err != nil {
|
||||
return nil, fmt.Errorf("error setting env %s: %w", env.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
var cfg Config
|
||||
|
||||
if err := cleanenv.ReadConfig(ConfigBasePath, &cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &cfg, nil
|
||||
}
|
||||
5
internal/config/constants.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package config
|
||||
|
||||
const (
|
||||
ConfigBasePath = "/home/alexorel/work/Molva/molva-backend/.build/config/local.example.yaml"
|
||||
)
|
||||
99
internal/config/dictionary.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package config
|
||||
|
||||
import "time"
|
||||
|
||||
type (
|
||||
Config struct {
|
||||
Env string `yaml:"env" env-default:"production"`
|
||||
Host string `yaml:"host" env-default:"localhost"`
|
||||
Port int `yaml:"port" env-default:"8000"`
|
||||
Keycloak Keycloak
|
||||
Broker Broker `yaml:"broker"`
|
||||
Secret SecretConfig
|
||||
EmailVerificationService EmailVerificationService `yaml:"emailVerificationService"`
|
||||
ValkeyCache ValkeyCacheConfig `yaml:"cache"`
|
||||
S3Storage S3StorageConfig `yaml:"s3Storage"`
|
||||
Database Database `yaml:"database"`
|
||||
Integration Integration
|
||||
Build BuildInfo
|
||||
}
|
||||
|
||||
BuildInfo struct {
|
||||
Version string
|
||||
Commit string
|
||||
Date string
|
||||
}
|
||||
|
||||
ValkeyCacheConfig struct {
|
||||
Addrs string `yaml:"-" env:"CACHE_ADDRS" env-default:"localhost:6379"`
|
||||
Password string `yaml:"-" env:"CACHE_PASSWORD" env-default:""`
|
||||
ReadOnly bool `yaml:"readOnly" env-default:"false"`
|
||||
DialTimeout time.Duration `yaml:"dialTimeout" env-default:"5s"`
|
||||
PoolSize int `yaml:"poolSize" env-default:"10"`
|
||||
DefaultTTL time.Duration `yaml:"defaultTtl" env-default:"1h"`
|
||||
RootCaFilePath string `yaml:"rootCaFilePath" env-default:""`
|
||||
}
|
||||
|
||||
S3StorageConfig struct {
|
||||
Bucket string `yaml:"bucket" env-default:""`
|
||||
DefaultLinkTTL time.Duration `yaml:"defaultLinkTtl" env-default:"1h"`
|
||||
}
|
||||
|
||||
SecretConfig struct {
|
||||
Key string `env:"SHORTENER_SECRET_KEY"` // 32-byte key
|
||||
}
|
||||
|
||||
Keycloak struct {
|
||||
BaseURL string `env:"KEYCLOAK_BASE_URL" env-default:"http://localhost"`
|
||||
Realm string `env:"KEYCLOAK_REALM" env-default:""`
|
||||
ClientId string `env:"KEYCLOAK_CLIENT_ID" env-default:""`
|
||||
ClientSecret string `env:"KEYCLOAK_CLIENT_SECRET" env-default:""`
|
||||
}
|
||||
|
||||
Broker struct {
|
||||
Host string `yaml:"-" env:"BROKER_HOST" env-default:"amqp://user:password@localhost"`
|
||||
Port int `yaml:"-" env:"BROKER_PORT" env-default:"5672"`
|
||||
UserName string `yaml:"-" env:"BROKER_USERNAME" env-default:"user"`
|
||||
Password string `yaml:"-" env:"BROKER_PASSWORD" env-default:"password"`
|
||||
NotificationsQueueName string `yaml:"notificationsQueueName" env-default:"notifications"`
|
||||
}
|
||||
|
||||
// TODO: че с этим делать? Его нигде нет (ни на дев, ни на прод)
|
||||
EmailVerificationService struct {
|
||||
APIKey string `yaml:"-" env-default:""`
|
||||
}
|
||||
|
||||
Database struct {
|
||||
Host string `yaml:"-" env:"DB_HOSTS"`
|
||||
Port uint16 `yaml:"-" env:"DB_PORT"`
|
||||
Username string `yaml:"-" env:"DB_USERNAME"`
|
||||
Password string `yaml:"-" env:"DB_PASSWORD"`
|
||||
DBName string `yaml:"-" env:"DB_DBNAME"`
|
||||
Schema string `yaml:"schema"`
|
||||
SSLMode string `yaml:"sslmode" env-default:"verify-full"`
|
||||
RootCaFilePath string `yaml:"rootCaFilePath" env-default:"/root/YandexInternalRootCA.crt"`
|
||||
}
|
||||
|
||||
Integration struct {
|
||||
Vkusvill VkusvillIntegration `yaml:"vkusvill"`
|
||||
}
|
||||
|
||||
VkusvillIntegration struct {
|
||||
ApiToken string `yaml:"-" env:"INTEGRATION_VKUSVILL_API_TOKEN"`
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
LocalDeploy struct {
|
||||
Deploy LocalDeployConfig `yaml:"deploy"`
|
||||
}
|
||||
|
||||
LocalDeployConfig struct {
|
||||
Env []LocalDeployConfigElement `yaml:"env"`
|
||||
}
|
||||
|
||||
LocalDeployConfigElement struct {
|
||||
Name string `yaml:"name"`
|
||||
Value string `yaml:"value"`
|
||||
}
|
||||
)
|
||||
17
internal/constants/errors.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package constants
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrInternalServerError = errors.New("internal server error")
|
||||
ErrBadRequest = errors.New("bad request")
|
||||
ErrForbidden = errors.New("forbidden")
|
||||
ErrNotFound = errors.New("not found")
|
||||
ErrUnauthorized = errors.New("unauthorized")
|
||||
ErrConflict = errors.New("conflict")
|
||||
ErrRequestTimeout = errors.New("request timeout")
|
||||
ErrNotImplemented = errors.New("not implemented")
|
||||
ErrBadGateway = errors.New("bad gateway")
|
||||
ErrServiceUnavailable = errors.New("service unavailable")
|
||||
ErrIntOutOfRange = errors.New("value is out of range for int32")
|
||||
)
|
||||
11
internal/constants/feed.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package constants
|
||||
|
||||
const (
|
||||
FeedEventsTableName = "feed_events"
|
||||
ClientTableName = "client"
|
||||
SubmissionTableName = "submission"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultFeedFilterLimit = 20
|
||||
)
|
||||
182
internal/constants/notifications.go
Normal file
@@ -0,0 +1,182 @@
|
||||
package constants
|
||||
|
||||
const (
|
||||
EmailNotificationMessageType = "email"
|
||||
|
||||
RegistrationNotificationMessageSubject = "Регистрация пользователя в системе приложения Molva"
|
||||
RegistrationNewUserAdmin = "Зарегистрирован новый пользователь приложения"
|
||||
EmailVerificationMessageSubject = "Подтверждение адреса электронной почты"
|
||||
TextNotificationContentType = "text/plain"
|
||||
HTMLNotificationContentType = "text/html"
|
||||
RegistrationNotificationText = `
|
||||
Добро пожаловать в Molva!
|
||||
|
||||
Здравствуйте, %s!
|
||||
|
||||
Спасибо за регистрацию в Molva. Мы рады видеть вас в нашем сообществе.
|
||||
|
||||
Теперь вы можете:
|
||||
- Получать персонализированные уведомления.
|
||||
- Настраивать свои предпочтения.
|
||||
- Использовать все возможности платформы.
|
||||
|
||||
Если у вас есть вопросы, не стесняйтесь обращаться в нашу службу поддержки!
|
||||
После проверки аккаунта наш администратор с вами свяжется
|
||||
|
||||
С уважением, команда Molva.
|
||||
|
||||
Это письмо отправлено автоматически, пожалуйста, не отвечайте на него.
|
||||
`
|
||||
|
||||
//nolint:gosec // there are no [potentially hardcoded] credentials in this message
|
||||
ForgotPasswordNotificationMessageSubject = "Восстановление пароля в системе приложения Molva"
|
||||
//nolint:gosec // there are no [potentially hardcoded] credentials in this message
|
||||
ForgotPasswordNotificationText = `
|
||||
Ваш код восстановления пароля: %s. Его можно использовать, чтобы сбросить пароль и зайти в свой аккаунт в Molva.
|
||||
|
||||
Если Вы не запрашивали восстановление доступа к аккаунту, пожалуйста, проигнорируйте это письмо.
|
||||
|
||||
С уважением, команда Molva.
|
||||
`
|
||||
)
|
||||
|
||||
const EmailVerificationTemplate = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
<body style="margin: 0; padding: 20px; font-family: Arial, sans-serif; background-color: #f5f5f5;">
|
||||
<div style="max-width: 600px; margin: 0 auto; background-color: #ffffff; padding: 40px; border-radius: 8px;">
|
||||
<h1 style="color: #333; font-size: 24px; margin: 0 0 30px 0;">MOLVA</h1>
|
||||
|
||||
<h2 style="color: #333; font-size: 20px; margin: 0 0 20px 0;">Подтвердите email</h2>
|
||||
|
||||
<p style="color: #555; font-size: 16px; line-height: 24px; margin: 0 0 10px 0;">
|
||||
Здравствуйте, %s!
|
||||
</p>
|
||||
|
||||
<p style="color: #555; font-size: 16px; line-height: 24px; margin: 0 0 30px 0;">
|
||||
Для завершения регистрации подтвердите ваш email адрес.
|
||||
</p>
|
||||
|
||||
<a href="%s" style="display: inline-block; padding: 12px 30px; background-color: #4A90E2; color: #ffffff; text-decoration: none; border-radius: 4px; font-size: 16px;">
|
||||
Подтвердить email
|
||||
</a>
|
||||
|
||||
<p style="color: #999; font-size: 14px; line-height: 20px; margin: 30px 0 10px 0;">
|
||||
Или скопируйте ссылку:
|
||||
</p>
|
||||
|
||||
<p style="color: #4A90E2; font-size: 14px; line-height: 20px; word-break: break-all; margin: 0 0 30px 0;">
|
||||
%s
|
||||
</p>
|
||||
|
||||
<p style="color: #999; font-size: 13px; line-height: 18px; margin: 0;">
|
||||
Ссылка действительна 24 часа.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
const EmailConfirmationPage = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Подтверждение Email</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f5f5f5;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
}
|
||||
.container {
|
||||
background: #ffffff;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||
text-align: center;
|
||||
max-width: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
.title {
|
||||
color: #333;
|
||||
margin-bottom: 20px;
|
||||
font-size: 22px;
|
||||
}
|
||||
.message {
|
||||
color: #555;
|
||||
font-size: 16px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.close-note {
|
||||
color: #777;
|
||||
font-size: 14px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="title" id="status-title">Идёт подтверждение...</div>
|
||||
<div class="message" id="status-message">Пожалуйста, подождите.</div>
|
||||
<div class="close-note" id="close-note" style="display:none;">
|
||||
Вы можете закрыть это окно.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
fetch("{{.VerificationURL}}", {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
const titleEl = document.getElementById("status-title");
|
||||
const msgEl = document.getElementById("status-message");
|
||||
const closeEl = document.getElementById("close-note");
|
||||
|
||||
if (response.ok) {
|
||||
titleEl.innerText = "Email успешно подтверждён!";
|
||||
msgEl.innerText = "Спасибо за подтверждение. Теперь вы можете вернуться на сайт MOLVA!";
|
||||
msgEl.style.color = "green";
|
||||
} else if (response.status === 400 || response.status === 404) {
|
||||
titleEl.innerText = "Неверная ссылка или токен";
|
||||
msgEl.innerText = "Проверьте правильность ссылки или запросите новую.";
|
||||
msgEl.style.color = "red";
|
||||
} else {
|
||||
titleEl.innerText = "Ошибка сервера";
|
||||
msgEl.innerText = "Попробуйте повторить позднее.";
|
||||
msgEl.style.color = "red";
|
||||
}
|
||||
|
||||
closeEl.style.display = "block";
|
||||
})
|
||||
.catch(() => {
|
||||
const titleEl = document.getElementById("status-title");
|
||||
const msgEl = document.getElementById("status-message");
|
||||
const closeEl = document.getElementById("close-note");
|
||||
|
||||
titleEl.innerText = "Не удалось подключиться";
|
||||
msgEl.innerText = "Проверьте интернет-соединение и попробуйте снова.";
|
||||
msgEl.style.color = "red";
|
||||
closeEl.style.display = "block";
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
const EmailNewUserRegistrationAdminMessage = `
|
||||
Зарегистрирован новый пользователь. Email подтверждён
|
||||
Email: %s
|
||||
Name: %s
|
||||
Type: %s
|
||||
`
|
||||
38
internal/constants/permissions.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package constants
|
||||
|
||||
type PermissionType string
|
||||
|
||||
const (
|
||||
Balance PermissionType = "balance"
|
||||
Vacancies PermissionType = "vacancies"
|
||||
Employees PermissionType = "employees"
|
||||
Profile PermissionType = "profile"
|
||||
Company PermissionType = "company"
|
||||
Submissions PermissionType = "submissions"
|
||||
)
|
||||
|
||||
func (p PermissionType) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
type PermissionValue string
|
||||
|
||||
const (
|
||||
NoPermission PermissionValue = "no_permission"
|
||||
CanView PermissionValue = "can_view"
|
||||
CanEdit PermissionValue = "can_edit"
|
||||
)
|
||||
|
||||
func (p PermissionValue) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
var PermissionLevels = map[PermissionValue]int{
|
||||
NoPermission: 1,
|
||||
CanView: 2,
|
||||
CanEdit: 3,
|
||||
}
|
||||
|
||||
var AllPermissions = []PermissionType{
|
||||
Vacancies, Balance, Company, Submissions, Profile, Employees, Submissions,
|
||||
}
|
||||
27
internal/constants/s3.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package constants
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
LogoLinkTTL = 55 * time.Minute
|
||||
LogoMaxSize = 10 << 20 // 10 MB
|
||||
BytesToDetectContentType = 512
|
||||
ParseMultipartFormAllFile = 0
|
||||
TempDirPermission = 0750
|
||||
TempLogoFilePattern = "logo-*.tmp"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultFileTTL = 30 * 24 * time.Hour //30 days
|
||||
)
|
||||
|
||||
var ValidImageTypes = map[string]bool{
|
||||
"image/png": true,
|
||||
"image/jpeg": true,
|
||||
"image/jpg": true,
|
||||
"image/webp": true,
|
||||
}
|
||||
|
||||
const (
|
||||
RefreshLogoCacheAsyncTimeout = 10 * time.Second
|
||||
)
|
||||
31
internal/constants/utils.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package constants
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
EmailVerificationServiceURL = "https://emailvalidation.abstractapi.com/v1/"
|
||||
DocumentsPath = "/opt/molva/docs"
|
||||
UserFilesBasePath = "/opt/molva/user_files"
|
||||
DefaultRetryTimeout = time.Second * 10
|
||||
DefaultContextTimeout = 30 * time.Second
|
||||
|
||||
DefaultPaginationPageSize = 20
|
||||
DefaultPaginationPage = 1
|
||||
)
|
||||
|
||||
const (
|
||||
AdminNotificationEmail = "information@molva.io"
|
||||
AdminNotificationId = 0
|
||||
)
|
||||
|
||||
var AdminNotificationEmails = []string{AdminNotificationEmail}
|
||||
|
||||
const (
|
||||
UserTypeAgentName = "Агент"
|
||||
UserTypeDistributorName = "Дистрибьютор"
|
||||
)
|
||||
|
||||
const (
|
||||
DistributorClientType = 1
|
||||
AgentClientType = 0
|
||||
)
|
||||
62
internal/database/client.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
pgdb "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/postgres"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
CreateUser(ctx context.Context, request *dbtypes.UserSaveRequest) (*dbtypes.UserSaveResponse, error)
|
||||
GetClientValidation(ctx context.Context, request *dbtypes.ClientValidationGetRequest) (*dbtypes.ClientValidationGetResponse, error)
|
||||
|
||||
GetVacancyIntegrationInfoById(ctx context.Context, vacancyId string) (string, *dbtypes.VacancyExtraFieldsTemplate, error)
|
||||
GetCompanyMetadataById(ctx context.Context, companyId string) (*dbtypes.CompanyMetadata, *dbtypes.CompanyExtraFieldsTemplate, error)
|
||||
|
||||
GetVacancyList(ctx context.Context, request *dbtypes.VacancyListGetRequest) (*dbtypes.VacancyListGetResponse, error)
|
||||
CreateVacancy(ctx context.Context, request *dbtypes.VacancyCreateRequest) (*dbtypes.VacancyCreateResponse, error)
|
||||
UpdateVacancy(ctx context.Context, request *dbtypes.VacancyUpdateRequest) (*dbtypes.VacancyUpdateResponse, error)
|
||||
DeleteVacancy(ctx context.Context, request *dbtypes.VacancyDeleteRequest) (*dbtypes.VacancyDeleteResponse, error)
|
||||
SendVacancyToModeration(ctx context.Context, request *dbtypes.SendVacancyToModerationRequest) (*dbtypes.SendVacancyToModerationResponse, error)
|
||||
|
||||
GetSubmissionList(ctx context.Context, request *dbtypes.SubmissionListGetRequest) (*dbtypes.SubmissionListGetResponse, error)
|
||||
CreateSubmission(ctx context.Context, request *dbtypes.SubmissionCreateRequest) (*dbtypes.SubmissionCreateResponse, error)
|
||||
UpdateSubmissionStatus(ctx context.Context, request *dbtypes.SubmissionStatusUpdateRequest) (*dbtypes.SubmissionStatusUpdateResponse, error)
|
||||
DeleteSubmission(ctx context.Context, request *dbtypes.SubmissionDeleteRequest) (*dbtypes.SubmissionDeleteResponse, error)
|
||||
|
||||
GetCompanyList(ctx context.Context, request *dbtypes.CompanyListGetRequest) (*dbtypes.CompanyListGetResponse, error)
|
||||
GetCompanyById(ctx context.Context, request *dbtypes.CompanyByIdGetRequest) (*dbtypes.CompanyByIdGetResponse, error)
|
||||
CreateCompany(ctx context.Context, request *dbtypes.CompanyCreateRequest) (*dbtypes.CompanyCreateResponse, error)
|
||||
UpdateCompany(ctx context.Context, request *dbtypes.CompanyUpdateRequest) (*dbtypes.CompanyUpdateResponse, error)
|
||||
// DeleteDistributorCompany(ctx context.Context, request *dbtypes.DistributorCompanyDeleteRequest) (*dbtypes.DistributorCompanyDeleteResponse, error)
|
||||
|
||||
GetProfileById(ctx context.Context, request *dbtypes.ProfileGetRequest) (*dbtypes.ProfileGetResponse, error)
|
||||
UpdateProfile(ctx context.Context, request *dbtypes.ProfileUpdateRequest) (*dbtypes.ProfileUpdateResponse, error)
|
||||
|
||||
GetBalance(ctx context.Context, request *dbtypes.BalanceGetRequest) (*dbtypes.BalanceGetResponse, error)
|
||||
|
||||
GetTransactionList(ctx context.Context, request *dbtypes.TransactionListGetRequest) (*dbtypes.TransactionListGetResponse, error)
|
||||
CreateTransaction(ctx context.Context, request *dbtypes.TransactionCreateRequest) (*dbtypes.TransactionCreateResponse, error)
|
||||
|
||||
GetBankAccountList(ctx context.Context, request *dbtypes.BankAccountListGetRequest) (*dbtypes.BankAccountListGetResponse, error)
|
||||
CreateBankAccount(ctx context.Context, request *dbtypes.BankAccountCreateRequest) (*dbtypes.BankAccountCreateResponse, error)
|
||||
UpdateBankAccount(ctx context.Context, request *dbtypes.BankAccountUpdateRequest) (*dbtypes.BankAccountUpdateResponse, error)
|
||||
DeleteBankAccount(ctx context.Context, request *dbtypes.BankAccountDeleteRequest) (*dbtypes.BankAccountDeleteResponse, error)
|
||||
}
|
||||
|
||||
func New(cType ClientType, c Config) (Client, error) {
|
||||
switch cType {
|
||||
case PostgresClientType:
|
||||
cfg, ok := c.(pgdb.PostgresConfig)
|
||||
if !ok {
|
||||
return nil, dberrors.ErrInvalidConfig
|
||||
}
|
||||
|
||||
return pgdb.NewClient(cfg)
|
||||
|
||||
default:
|
||||
return nil, dberrors.ErrClientType
|
||||
}
|
||||
}
|
||||
10
internal/database/domain.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package database
|
||||
|
||||
type (
|
||||
ClientType int
|
||||
Config any
|
||||
)
|
||||
|
||||
const (
|
||||
PostgresClientType ClientType = iota
|
||||
)
|
||||
16
internal/database/errors/errors.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package dberrors
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrClientType = errors.New("invalid client type")
|
||||
ErrInvalidConfig = errors.New("invalid config")
|
||||
|
||||
ErrUnimplemented = errors.New("unimplemented")
|
||||
|
||||
ErrBadRequest = errors.New("bad request")
|
||||
ErrForbidden = errors.New("forbidden")
|
||||
ErrNotFound = errors.New("not found")
|
||||
ErrConflict = errors.New("conflict")
|
||||
ErrInternal = errors.New("internal")
|
||||
)
|
||||
100
internal/database/postgres/balance.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package pgdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
"github.com/Masterminds/squirrel"
|
||||
)
|
||||
|
||||
func (c *client) GetBalance(
|
||||
ctx context.Context,
|
||||
request *dbtypes.BalanceGetRequest,
|
||||
) (*dbtypes.BalanceGetResponse, error) {
|
||||
if request == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
balancesTable = fmt.Sprintf("%s.%s", c.config.Schema, BalancesTableName)
|
||||
)
|
||||
|
||||
getBalance := psql.Select(
|
||||
"raw_balance", "clean_balance",
|
||||
).From(balancesTable).
|
||||
Where(squirrel.Eq{"owner_id": request.OwnerId})
|
||||
|
||||
query, args, err := getBalance.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building get balance query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := c.db.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var (
|
||||
balance dbtypes.Balance
|
||||
)
|
||||
|
||||
if err := row.Scan(&balance.RawBalance, &balance.CleanBalance); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
return &dbtypes.BalanceGetResponse{
|
||||
Balance: &balance,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *client) createBalance(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
request *dbtypes.BalanceCreateRequest,
|
||||
) error {
|
||||
if request == nil {
|
||||
return fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
balancesTable = fmt.Sprintf("%s.%s", c.config.Schema, BalancesTableName)
|
||||
)
|
||||
|
||||
createBalance := psql.Insert(balancesTable).
|
||||
Columns(
|
||||
"id", "owner_id", "raw_balance", "clean_balance",
|
||||
).
|
||||
Values(
|
||||
request.Id, request.OwnerId, request.RawBalance, request.CleanBalance,
|
||||
)
|
||||
|
||||
query, args, err := createBalance.ToSql()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error building 'create balance' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error executing 'create balance' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error getting rows affected for 'create balance' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
313
internal/database/postgres/bank_account.go
Normal file
@@ -0,0 +1,313 @@
|
||||
package pgdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// ALERT: intergrate safety checks
|
||||
|
||||
func (c *client) GetBankAccountList(
|
||||
ctx context.Context,
|
||||
request *dbtypes.BankAccountListGetRequest,
|
||||
) (*dbtypes.BankAccountListGetResponse, error) {
|
||||
if request == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
bankAccountsTable = fmt.Sprintf("%s.%s", c.config.Schema, BankAccountsTableName)
|
||||
)
|
||||
|
||||
getAccounts := psql.Select(
|
||||
"id", "owner_id", "account_number", "bank_name", "bik",
|
||||
"correspondent_account", "is_primary", "created_at", "updated_at",
|
||||
).From(bankAccountsTable).
|
||||
Where(squirrel.Eq{"owner_id": request.OwnerId})
|
||||
|
||||
query, args, err := getAccounts.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building get bank accounts query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rows, err := c.db.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing get bank accounts query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
var accounts []dbtypes.BankAccount
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
accountNumber, bankName, bik, correspondentAccount sql.NullString
|
||||
bankAccount dbtypes.BankAccount
|
||||
)
|
||||
|
||||
if err := rows.Scan(
|
||||
&bankAccount.Id, &bankAccount.OwnerId, &accountNumber, &bankName, &bik,
|
||||
&correspondentAccount, &bankAccount.IsPrimary, &bankAccount.CreatedAt, &bankAccount.UpdatedAt,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if accountNumber.Valid {
|
||||
bankAccount.AccountName = accountNumber.String
|
||||
}
|
||||
|
||||
if bankName.Valid {
|
||||
bankAccount.BankName = bankName.String
|
||||
}
|
||||
|
||||
if bik.Valid {
|
||||
bankAccount.Bik = bik.String
|
||||
}
|
||||
|
||||
if correspondentAccount.Valid {
|
||||
bankAccount.CorrespondentAccount = correspondentAccount.String
|
||||
}
|
||||
|
||||
accounts = append(accounts, bankAccount)
|
||||
}
|
||||
|
||||
return &dbtypes.BankAccountListGetResponse{
|
||||
BankAccounts: accounts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *client) CreateBankAccount(
|
||||
ctx context.Context,
|
||||
request *dbtypes.BankAccountCreateRequest,
|
||||
) (*dbtypes.BankAccountCreateResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
bankAccountsTable = fmt.Sprintf("%s.%s", c.config.Schema, BankAccountsTableName)
|
||||
)
|
||||
|
||||
// TODO: use normal uuid after DB reengineering
|
||||
bankAccountId := fmt.Sprintf("%sBNK", strings.ReplaceAll(uuid.NewString(), "-", ""))
|
||||
|
||||
createBankAccount := psql.Insert(bankAccountsTable).
|
||||
Columns(
|
||||
"id", "owner_id", "account_number", "bank_name", "bik", "correspondent_account", "is_primary",
|
||||
).
|
||||
Values(
|
||||
bankAccountId, request.OwnerId, request.AccountNumber, request.BankName,
|
||||
request.Bik, request.CorrespondentAccount, request.IsPrimary,
|
||||
)
|
||||
|
||||
query, args, err := createBankAccount.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building create bank account query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := c.db.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing create bank account query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for create bank account query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return &dbtypes.BankAccountCreateResponse{
|
||||
Id: bankAccountId,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *client) UpdateBankAccount(
|
||||
ctx context.Context,
|
||||
request *dbtypes.BankAccountUpdateRequest,
|
||||
) (*dbtypes.BankAccountUpdateResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := c.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error starting transaction: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
result, err := c.updateBankAccount(ctx, tx, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error updating bank account: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, fmt.Errorf("%w: error committing transaction: %w", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *client) updateBankAccount(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
request *dbtypes.BankAccountUpdateRequest,
|
||||
) (*dbtypes.BankAccountUpdateResponse, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
bankAccountsTable = fmt.Sprintf("%s.%s", c.config.Schema, BankAccountsTableName)
|
||||
)
|
||||
|
||||
updateAccount := psql.Update(bankAccountsTable).
|
||||
Where(squirrel.Eq{"id": request.Id})
|
||||
|
||||
if request.AccountNumber != nil {
|
||||
updateAccount = updateAccount.Set("account_number", *request.AccountNumber)
|
||||
}
|
||||
|
||||
// TODO: uncomment when DB supports it
|
||||
// if request.AccountName != nil {
|
||||
// updateAccount = updateAccount.Set("account_name", *request.AccountName)
|
||||
// }
|
||||
|
||||
if request.BankName != nil {
|
||||
updateAccount = updateAccount.Set("bank_name", *request.BankName)
|
||||
}
|
||||
|
||||
if request.Bik != nil {
|
||||
updateAccount = updateAccount.Set("bik", *request.Bik)
|
||||
}
|
||||
|
||||
if request.CorrespondentAccount != nil {
|
||||
updateAccount = updateAccount.Set("correspondent_account", *request.CorrespondentAccount)
|
||||
}
|
||||
|
||||
if request.IsPrimary != nil {
|
||||
if *request.IsPrimary {
|
||||
if err := c.unmarkPrimaryBankAccount(ctx, driver, request.Id); err != nil {
|
||||
return nil, fmt.Errorf("error unmarking currently primary bank account: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// QnA: what if the update makes all BAs non-primary?
|
||||
updateAccount = updateAccount.Set("is_primary", *request.IsPrimary)
|
||||
}
|
||||
|
||||
query, args, err := updateAccount.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building 'update bank account' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing 'update bank account' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for 'update bank account' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return &dbtypes.BankAccountUpdateResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *client) unmarkPrimaryBankAccount(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
bankAccountId string,
|
||||
) error {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
bankAccountsTable = fmt.Sprintf("%s.%s", c.config.Schema, BankAccountsTableName)
|
||||
)
|
||||
|
||||
getOwnerId := psql.Select(
|
||||
"owner_id", "is_primary",
|
||||
).From(bankAccountsTable).
|
||||
Where(squirrel.Eq{"id": bankAccountId}).
|
||||
Suffix("FOR UPDATE")
|
||||
|
||||
query, args, err := getOwnerId.ToSql()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error building 'get owner id of bank account' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := driver.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var (
|
||||
ownerId string
|
||||
isPrimary bool
|
||||
)
|
||||
|
||||
if err := row.Scan(&ownerId, &isPrimary); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return fmt.Errorf("%w: error scanning row for 'get owner id of bank account' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if isPrimary {
|
||||
return nil
|
||||
}
|
||||
|
||||
unmarkPrimaryBA := psql.Update(bankAccountsTable).
|
||||
Set("is_primary", false).
|
||||
Where(squirrel.Eq{
|
||||
"owner_id": ownerId,
|
||||
"is_primary": true,
|
||||
})
|
||||
|
||||
query, args, err = unmarkPrimaryBA.ToSql()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error building 'unmark primary bank account' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error executing 'unmark primary bank account' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error getting rows affected for 'unmark primary bank account' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return fmt.Errorf("%w: error unmarking primary bank account: no rows affected", dberrors.ErrInternal)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *client) DeleteBankAccount(
|
||||
ctx context.Context,
|
||||
request *dbtypes.BankAccountDeleteRequest,
|
||||
) (*dbtypes.BankAccountDeleteResponse, error) {
|
||||
return nil, dberrors.ErrUnimplemented
|
||||
}
|
||||
107
internal/database/postgres/client.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package pgdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/stdlib"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
// Интерфейс передается в неэкспортируемые функции
|
||||
// нужен для того, чтобы не зависило от того, что передаём
|
||||
// транзацию или обычное соединение
|
||||
type Driver interface {
|
||||
// QueryContext executes a query that returns rows, typically a SELECT.
|
||||
// The args are for any placeholder parameters in the query.
|
||||
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
|
||||
|
||||
// QueryRowContext executes a query that is expected to return at most one row.
|
||||
// QueryRowContext always returns a non-nil value. Errors are deferred until
|
||||
// [Row]'s Scan method is called.
|
||||
// If the query selects no rows, the [*Row.Scan] will return [ErrNoRows].
|
||||
// Otherwise, [*Row.Scan] scans the first selected row and discards
|
||||
// the rest.
|
||||
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
|
||||
|
||||
// ExecContext executes a query without returning any rows.
|
||||
// The args are for any placeholder parameters in the query.
|
||||
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
|
||||
}
|
||||
|
||||
type PostgresConfig struct {
|
||||
Host string
|
||||
Port uint16
|
||||
Username string
|
||||
Password string
|
||||
Database string
|
||||
Schema string
|
||||
SSLMode string
|
||||
SSLRootCert string
|
||||
}
|
||||
|
||||
type client struct {
|
||||
config PostgresConfig
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
func NewClient(cfg PostgresConfig) (*client, error) {
|
||||
rootCertPool := x509.NewCertPool()
|
||||
|
||||
caCert, err := os.ReadFile(cfg.SSLRootCert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read CA cert: %w", err)
|
||||
}
|
||||
|
||||
if ok := rootCertPool.AppendCertsFromPEM(caCert); !ok {
|
||||
return nil, fmt.Errorf("failed to append CA cert to pool")
|
||||
}
|
||||
|
||||
tlsConfig := &tls.Config{
|
||||
RootCAs: rootCertPool,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
//nolint:gosec // TODO: set server name
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
config, err := pgx.ParseConfig("")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse [empty] config: %w", err)
|
||||
}
|
||||
|
||||
config.Host = cfg.Host
|
||||
config.Port = cfg.Port
|
||||
config.Database = cfg.Database
|
||||
config.User = cfg.Username
|
||||
config.Password = cfg.Password
|
||||
config.TLSConfig = tlsConfig
|
||||
config.RuntimeParams = map[string]string{"sslmode": cfg.SSLMode}
|
||||
|
||||
db := sqlx.NewDb(stdlib.OpenDB(*config), "pgx")
|
||||
|
||||
if err := db.Ping(); err != nil {
|
||||
return nil, fmt.Errorf("failed to ping postgres: %w", err)
|
||||
}
|
||||
|
||||
return &client{
|
||||
config: cfg,
|
||||
db: db,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func countOffset(page, pageSize uint64) uint64 {
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
if pageSize == 0 {
|
||||
pageSize = DefaultPaginationPageSize
|
||||
}
|
||||
|
||||
return (page - 1) * pageSize
|
||||
}
|
||||
506
internal/database/postgres/company.go
Normal file
@@ -0,0 +1,506 @@
|
||||
package pgdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
func CompanyModerationStatusIdToString(status int32) dbtypes.CompanyModerationStatus {
|
||||
switch status {
|
||||
case 0:
|
||||
return dbtypes.CompanyModerationStatusPending
|
||||
case 1:
|
||||
return dbtypes.CompanyModerationStatusApproved
|
||||
case 2:
|
||||
return dbtypes.CompanyModerationStatusRejected
|
||||
case 3:
|
||||
return dbtypes.CompanyModerationStatusNew
|
||||
default:
|
||||
return dbtypes.CompanyModerationStatusNew
|
||||
}
|
||||
}
|
||||
|
||||
func CompanyModerationStatusStringToId(status dbtypes.CompanyModerationStatus) int32 {
|
||||
switch status {
|
||||
case dbtypes.CompanyModerationStatusPending:
|
||||
return 0
|
||||
case dbtypes.CompanyModerationStatusApproved:
|
||||
return 1
|
||||
case dbtypes.CompanyModerationStatusRejected:
|
||||
return 2
|
||||
case dbtypes.CompanyModerationStatusNew:
|
||||
return 3
|
||||
default:
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:gocognit // TODO: refactor
|
||||
func (c *client) GetCompanyList(
|
||||
ctx context.Context,
|
||||
request *dbtypes.CompanyListGetRequest,
|
||||
) (*dbtypes.CompanyListGetResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
companiesTable = fmt.Sprintf("%s.%s", c.config.Schema, CompaniesTableName)
|
||||
)
|
||||
|
||||
getComList := psql.Select(
|
||||
"id", "uid", "name", "legal_person", "description", "website",
|
||||
"physical_address", "legal_address", "inn", "is_active", // TODO: add KPP when DB supports it
|
||||
"has_moderation_ticket", "staff", "metadata", "additional_fields_tmpl",
|
||||
).
|
||||
From(companiesTable).
|
||||
Where(squirrel.Eq{"uid": request.Id})
|
||||
|
||||
query, args, err := getComList.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building get distributor company list query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rows, err := c.db.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing get distributor company list query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
var res dbtypes.CompanyListGetResponse
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
name, legalPerson, description, website, physicalAddress sql.NullString
|
||||
legalAddress, inn, metadata, additionalFieldsTmpl sql.NullString
|
||||
staff pq.StringArray
|
||||
company dbtypes.Company
|
||||
)
|
||||
|
||||
if err := rows.Scan(
|
||||
&company.Id, &company.OwnerId, &name, &legalPerson, &description, &website,
|
||||
&physicalAddress, &legalAddress, &inn, &company.IsActive,
|
||||
&company.HasModerationTicket, &staff, &metadata, &additionalFieldsTmpl,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if name.Valid {
|
||||
company.Name = &name.String
|
||||
}
|
||||
|
||||
if legalPerson.Valid {
|
||||
company.LegalPerson = &legalPerson.String
|
||||
}
|
||||
|
||||
if description.Valid {
|
||||
company.Description = &description.String
|
||||
}
|
||||
|
||||
if website.Valid {
|
||||
company.Website = &website.String
|
||||
}
|
||||
|
||||
if physicalAddress.Valid {
|
||||
company.PhysicalAddress = &physicalAddress.String
|
||||
}
|
||||
|
||||
if legalAddress.Valid {
|
||||
company.LegalAddress = &legalAddress.String
|
||||
}
|
||||
|
||||
if inn.Valid {
|
||||
company.Inn = &inn.String
|
||||
}
|
||||
|
||||
company.Staff = staff
|
||||
|
||||
if metadata.Valid {
|
||||
company.Metadata = &metadata.String
|
||||
}
|
||||
|
||||
if additionalFieldsTmpl.Valid {
|
||||
company.ExtraFieldsTemplate = &additionalFieldsTmpl.String
|
||||
}
|
||||
|
||||
res.Companies = append(res.Companies, company)
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func (c *client) GetCompanyById(
|
||||
ctx context.Context,
|
||||
request *dbtypes.CompanyByIdGetRequest,
|
||||
) (*dbtypes.CompanyByIdGetResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
companiesTable = fmt.Sprintf("%s.%s", c.config.Schema, CompaniesTableName)
|
||||
)
|
||||
|
||||
getComList := psql.Select(
|
||||
"id", "uid", "name", "legal_person", "description", "website",
|
||||
"physical_address", "legal_address", "inn", "is_active", // TODO: add KPP when DB supports it
|
||||
"has_moderation_ticket", "staff", "metadata", "additional_fields_tmpl",
|
||||
).
|
||||
From(companiesTable).
|
||||
Where(squirrel.And{
|
||||
squirrel.Eq{"id": request.CompanyId},
|
||||
squirrel.Eq{"uid": request.Id},
|
||||
})
|
||||
|
||||
query, args, err := getComList.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building get distributor company list query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := c.db.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var (
|
||||
name, legalPerson, description, website, physicalAddress sql.NullString
|
||||
legalAddress, inn, metadata, additionalFieldsTmpl sql.NullString
|
||||
staff pq.StringArray
|
||||
company dbtypes.Company
|
||||
)
|
||||
|
||||
if err := row.Scan(
|
||||
&company.Id, &company.OwnerId, &name, &legalPerson, &description, &website,
|
||||
&physicalAddress, &legalAddress, &inn, &company.IsActive,
|
||||
&company.HasModerationTicket, &staff, &metadata, &additionalFieldsTmpl,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if name.Valid {
|
||||
company.Name = &name.String
|
||||
}
|
||||
|
||||
if legalPerson.Valid {
|
||||
company.LegalPerson = &legalPerson.String
|
||||
}
|
||||
|
||||
if description.Valid {
|
||||
company.Description = &description.String
|
||||
}
|
||||
|
||||
if website.Valid {
|
||||
company.Website = &website.String
|
||||
}
|
||||
|
||||
if physicalAddress.Valid {
|
||||
company.PhysicalAddress = &physicalAddress.String
|
||||
}
|
||||
|
||||
if legalAddress.Valid {
|
||||
company.LegalAddress = &legalAddress.String
|
||||
}
|
||||
|
||||
if inn.Valid {
|
||||
company.Inn = &inn.String
|
||||
}
|
||||
|
||||
company.Staff = staff
|
||||
|
||||
if metadata.Valid {
|
||||
company.Metadata = &metadata.String
|
||||
}
|
||||
|
||||
if additionalFieldsTmpl.Valid {
|
||||
company.ExtraFieldsTemplate = &additionalFieldsTmpl.String
|
||||
}
|
||||
|
||||
return &dbtypes.CompanyByIdGetResponse{Company: company}, nil
|
||||
}
|
||||
|
||||
func (c *client) CreateCompany(
|
||||
ctx context.Context,
|
||||
request *dbtypes.CompanyCreateRequest,
|
||||
) (*dbtypes.CompanyCreateResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := c.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error starting transaction: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
res, err := c.createCompany(ctx, tx, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating company: %w", err)
|
||||
}
|
||||
|
||||
if err := c.createCompanyValidationTicket(ctx, tx, res.Id, request); err != nil {
|
||||
return nil, fmt.Errorf("error creating company validation ticket: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, fmt.Errorf("error committing transaction: %w", err)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *client) createCompany(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
request *dbtypes.CompanyCreateRequest,
|
||||
) (*dbtypes.CompanyCreateResponse, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
companyTable = fmt.Sprintf("%s.%s", c.config.Schema, CompaniesTableName)
|
||||
)
|
||||
|
||||
// TODO: use normal uuid after DB reengineering
|
||||
comId := fmt.Sprintf("%sCOM", strings.ReplaceAll(uuid.NewString(), "-", ""))
|
||||
|
||||
createCompany := psql.Insert(companyTable).
|
||||
Columns(
|
||||
"id", "uid", "is_active", "has_moderation_ticket", "metadata", "additional_fields_tmpl",
|
||||
).
|
||||
Values(
|
||||
comId, request.OwnerId, false, true, request.Metadata, request.ExtraFieldsTemplate,
|
||||
)
|
||||
|
||||
query, args, err := createCompany.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building create company query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing create company query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for create company query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return &dbtypes.CompanyCreateResponse{Id: comId}, nil
|
||||
}
|
||||
|
||||
func (c *client) createCompanyValidationTicket(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
companyId string,
|
||||
request *dbtypes.CompanyCreateRequest,
|
||||
) error {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
comValTable = fmt.Sprintf("%s.%s", c.config.Schema, CompanyValidationTicketsTableName)
|
||||
)
|
||||
|
||||
var (
|
||||
ticketId = fmt.Sprintf("%sTCK", strings.ReplaceAll(uuid.NewString(), "-", ""))
|
||||
)
|
||||
|
||||
createCompany := psql.Insert(comValTable).
|
||||
Columns(
|
||||
"id", "company_id", "name", "legal_person", "description", "website",
|
||||
"physical_address", "legal_address", "inn", // TODO: add KPP when DB supports it
|
||||
"staff", "status",
|
||||
).
|
||||
Values(
|
||||
ticketId, companyId, request.Name, request.LegalPerson, request.Description, request.Website,
|
||||
request.PhysicalAddress, request.LegalAddress, request.Inn,
|
||||
request.Staff, CompanyModerationStatusStringToId(dbtypes.CompanyModerationStatusPending), // TODO: switch to status "NEW"
|
||||
)
|
||||
|
||||
query, args, err := createCompany.ToSql()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error building create company moderation ticket query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error executing create company moderation ticket query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error getting rows affected for create company moderation ticket query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *client) UpdateCompany(
|
||||
ctx context.Context,
|
||||
request *dbtypes.CompanyUpdateRequest,
|
||||
) (*dbtypes.CompanyUpdateResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := c.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error starting transaction: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
res, err := c.updateCompany(ctx, tx, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error updating company: %w", err)
|
||||
}
|
||||
|
||||
if err := c.updateCompanyValidationTicket(ctx, tx, request.Id, request); err != nil {
|
||||
return nil, fmt.Errorf("error updating company validation ticket: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, fmt.Errorf("error committing transaction: %w", err)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *client) updateCompany(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
request *dbtypes.CompanyUpdateRequest,
|
||||
) (*dbtypes.CompanyUpdateResponse, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
companyTable = fmt.Sprintf("%s.%s", c.config.Schema, CompaniesTableName)
|
||||
)
|
||||
|
||||
updateCompany := psql.Update(companyTable).
|
||||
SetMap(map[string]any{
|
||||
"is_active": false,
|
||||
"has_moderation_ticket": true,
|
||||
"metadata": request.Metadata,
|
||||
"additional_fields_tmpl": request.ExtraFields,
|
||||
}).
|
||||
Where(squirrel.Eq{"id": request.Id})
|
||||
|
||||
query, args, err := updateCompany.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building update company query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing update company query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for update company query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return &dbtypes.CompanyUpdateResponse{}, nil
|
||||
}
|
||||
|
||||
// NOTE: do we believe that every company has a moderation ticket?
|
||||
func (c *client) updateCompanyValidationTicket(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
companyId string,
|
||||
request *dbtypes.CompanyUpdateRequest,
|
||||
) error {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
comValTable = fmt.Sprintf("%s.%s", c.config.Schema, CompanyValidationTicketsTableName)
|
||||
)
|
||||
|
||||
updateCompany := psql.Update(comValTable).
|
||||
Where(squirrel.Eq{"company_id": companyId})
|
||||
|
||||
if request.Name != nil {
|
||||
updateCompany = updateCompany.Set("name", *request.Name)
|
||||
}
|
||||
|
||||
if request.LegalPerson != nil {
|
||||
updateCompany = updateCompany.Set("legal_person", *request.LegalPerson)
|
||||
}
|
||||
|
||||
if request.Description != nil {
|
||||
updateCompany = updateCompany.Set("description", *request.Description)
|
||||
}
|
||||
|
||||
if request.Website != nil {
|
||||
updateCompany = updateCompany.Set("website", *request.Website)
|
||||
}
|
||||
|
||||
if request.PhysicalAddress != nil {
|
||||
updateCompany = updateCompany.Set("physical_address", *request.PhysicalAddress)
|
||||
}
|
||||
|
||||
if request.LegalAddress != nil {
|
||||
updateCompany = updateCompany.Set("legal_address", *request.LegalAddress)
|
||||
}
|
||||
|
||||
if request.Inn != nil {
|
||||
updateCompany = updateCompany.Set("inn", *request.Inn)
|
||||
}
|
||||
|
||||
if len(request.Staff) > 0 {
|
||||
updateCompany = updateCompany.Set("staff", request.Staff)
|
||||
}
|
||||
|
||||
query, args, err := updateCompany.ToSql()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error building update company moderation ticket query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error executing update company moderation ticket query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error getting rows affected for update company moderation ticket query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
23
internal/database/postgres/domain.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package pgdb
|
||||
|
||||
const (
|
||||
BalancesTableName = "balances"
|
||||
BankAccountsTableName = "company_bank_accounts"
|
||||
CompaniesTableName = "company"
|
||||
CompanyValidationTicketsTableName = "company_validation"
|
||||
SubmissionsTableName = "submission"
|
||||
TransactionsTableName = "transactions"
|
||||
VacanciesTableName = "vacancy"
|
||||
VacancyCandidatesTableName = "vacancy_candidates"
|
||||
VacancyDescriptionHistoryTableName = "vacancy_moderation_descriptions"
|
||||
UsersTableName = "client"
|
||||
UserValidationTableName = "client_validation"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultPaginationPageSize = 20
|
||||
)
|
||||
|
||||
const (
|
||||
PGErrUniqueViolation = "23505"
|
||||
)
|
||||
128
internal/database/postgres/integration.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package pgdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
"github.com/Masterminds/squirrel"
|
||||
)
|
||||
|
||||
func (c *client) GetVacancyIntegrationInfoById(
|
||||
ctx context.Context,
|
||||
vacancyId string,
|
||||
) (string, *dbtypes.VacancyExtraFieldsTemplate, error) {
|
||||
return c.getVacancyIntegrationInfoById(ctx, c.db, vacancyId)
|
||||
}
|
||||
|
||||
func (c *client) getVacancyIntegrationInfoById(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
vacancyId string,
|
||||
) (string, *dbtypes.VacancyExtraFieldsTemplate, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
vacancyTable = fmt.Sprintf("%s.%s", c.config.Schema, VacanciesTableName)
|
||||
)
|
||||
|
||||
getCompanyIdQuery := psql.Select("company_id", "additional_fields").
|
||||
From(vacancyTable).
|
||||
Where(squirrel.Eq{"id": vacancyId})
|
||||
|
||||
query, args, err := getCompanyIdQuery.ToSql()
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("%w: error building query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := driver.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var (
|
||||
companyId string
|
||||
fieldsString sql.NullString
|
||||
fields dbtypes.VacancyExtraFieldsTemplate
|
||||
)
|
||||
|
||||
if err := row.Scan(&companyId, &fieldsString); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return "", nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return "", nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if fieldsString.Valid {
|
||||
if err := json.Unmarshal([]byte(fieldsString.String), &fields); err != nil {
|
||||
return "", nil, fmt.Errorf("%w: error unmarshalling fields: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
}
|
||||
|
||||
return companyId, &fields, nil
|
||||
}
|
||||
|
||||
func (c *client) GetCompanyMetadataById(
|
||||
ctx context.Context,
|
||||
companyId string,
|
||||
) (*dbtypes.CompanyMetadata, *dbtypes.CompanyExtraFieldsTemplate, error) {
|
||||
return c.getCompanyMetadataById(ctx, c.db, companyId)
|
||||
}
|
||||
|
||||
func (c *client) getCompanyMetadataById(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
companyId string,
|
||||
) (*dbtypes.CompanyMetadata, *dbtypes.CompanyExtraFieldsTemplate, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
companyTable = fmt.Sprintf("%s.%s", c.config.Schema, CompaniesTableName)
|
||||
)
|
||||
|
||||
getCompanyMetadataQuery := psql.Select(
|
||||
"metadata",
|
||||
"additional_fields_tmpl",
|
||||
).
|
||||
From(companyTable).
|
||||
Where(squirrel.Eq{"id": companyId})
|
||||
|
||||
query, args, err := getCompanyMetadataQuery.ToSql()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("%w: error building query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := driver.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var (
|
||||
metadataString sql.NullString
|
||||
metadata dbtypes.CompanyMetadata
|
||||
|
||||
fieldsTemplateString sql.NullString
|
||||
fieldsTemplate dbtypes.CompanyExtraFieldsTemplate
|
||||
)
|
||||
|
||||
if err := row.Scan(&metadataString, &fieldsTemplateString); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if metadataString.Valid {
|
||||
if err := json.Unmarshal([]byte(metadataString.String), &metadata); err != nil {
|
||||
return nil, nil, fmt.Errorf("%w: error unmarshalling metadata: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
}
|
||||
|
||||
if fieldsTemplateString.Valid {
|
||||
if err := json.Unmarshal([]byte(fieldsTemplateString.String), &fieldsTemplate); err != nil {
|
||||
return nil, nil, fmt.Errorf("%w: error unmarshalling fields template: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
}
|
||||
|
||||
return &metadata, &fieldsTemplate, nil
|
||||
}
|
||||
130
internal/database/postgres/profile.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package pgdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
func (c *client) GetProfileById(
|
||||
ctx context.Context,
|
||||
request *dbtypes.ProfileGetRequest,
|
||||
) (*dbtypes.ProfileGetResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
usersTable = fmt.Sprintf("%s.%s", c.config.Schema, UsersTableName)
|
||||
)
|
||||
|
||||
getProfile := psql.Select(
|
||||
"uid", "name", "phone", "email",
|
||||
).From(usersTable).
|
||||
Where(squirrel.Eq{"uid": request.Id})
|
||||
|
||||
query, args, err := getProfile.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building get profile query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := c.db.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var (
|
||||
name, phoneNumber, email sql.NullString
|
||||
profile dbtypes.Profile
|
||||
)
|
||||
|
||||
if err := row.Scan(&profile.Id, &name, &phoneNumber, &email); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if name.Valid {
|
||||
profile.Name = name.String
|
||||
}
|
||||
|
||||
if phoneNumber.Valid {
|
||||
profile.PhoneNumber = phoneNumber.String
|
||||
}
|
||||
|
||||
if email.Valid {
|
||||
profile.Email = email.String
|
||||
}
|
||||
|
||||
return &dbtypes.ProfileGetResponse{
|
||||
Profile: &profile,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *client) UpdateProfile(
|
||||
ctx context.Context,
|
||||
request *dbtypes.ProfileUpdateRequest,
|
||||
) (*dbtypes.ProfileUpdateResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
if request.Name == nil && request.PhoneNumber == nil && request.Email == nil {
|
||||
return nil, fmt.Errorf("%w: nothing to update", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
usersTable = fmt.Sprintf("%s.%s", c.config.Schema, UsersTableName)
|
||||
)
|
||||
|
||||
updateProfile := psql.Update(usersTable).
|
||||
Where(squirrel.Eq{"uid": request.Id})
|
||||
|
||||
if request.Name != nil {
|
||||
updateProfile = updateProfile.Set("name", *request.Name)
|
||||
}
|
||||
|
||||
if request.PhoneNumber != nil {
|
||||
updateProfile = updateProfile.Set("phone", *request.PhoneNumber)
|
||||
}
|
||||
|
||||
if request.Email != nil {
|
||||
updateProfile = updateProfile.Set("email", *request.Email)
|
||||
}
|
||||
|
||||
query, args, err := updateProfile.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building update profile query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := c.db.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
if pqErr, ok := err.(*pq.Error); ok {
|
||||
if pqErr.Code == PGErrUniqueViolation {
|
||||
return nil, dberrors.ErrConflict
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error executing update profile query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for update profile query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return &dbtypes.ProfileUpdateResponse{}, nil
|
||||
}
|
||||
494
internal/database/postgres/submission.go
Normal file
@@ -0,0 +1,494 @@
|
||||
package pgdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func SubmissionStatusIdToString(status int32) dbtypes.SubmissionStatus {
|
||||
switch status {
|
||||
case 0:
|
||||
return dbtypes.SubStatusUnspecified
|
||||
case 1:
|
||||
return dbtypes.SubStatusNew
|
||||
case 2:
|
||||
return dbtypes.SubStatusPending
|
||||
case 3:
|
||||
return dbtypes.SubStatusOnInterview
|
||||
case 4:
|
||||
return dbtypes.SubStatusRejected
|
||||
case 5:
|
||||
return dbtypes.SubStatusCancelled
|
||||
case 6:
|
||||
return dbtypes.SubStatusApproved
|
||||
default:
|
||||
return dbtypes.SubStatusUnspecified
|
||||
}
|
||||
}
|
||||
|
||||
func SubmissionStatusStringToId(status dbtypes.SubmissionStatus) int32 {
|
||||
switch status {
|
||||
case dbtypes.SubStatusUnspecified:
|
||||
return 0
|
||||
case dbtypes.SubStatusNew:
|
||||
return 1
|
||||
case dbtypes.SubStatusPending:
|
||||
return 2
|
||||
case dbtypes.SubStatusOnInterview:
|
||||
return 3
|
||||
case dbtypes.SubStatusRejected:
|
||||
return 4
|
||||
case dbtypes.SubStatusCancelled:
|
||||
return 5
|
||||
case dbtypes.SubStatusApproved:
|
||||
return 6
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:gocognit // not so hard
|
||||
func (c *client) GetSubmissionList(
|
||||
ctx context.Context,
|
||||
request *dbtypes.SubmissionListGetRequest,
|
||||
) (*dbtypes.SubmissionListGetResponse, error) {
|
||||
if request == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
submissionsTable = fmt.Sprintf("%s.%s", c.config.Schema, SubmissionsTableName)
|
||||
)
|
||||
|
||||
getSubmissions := psql.Select(
|
||||
"id", "uid", "vacancy_id", "submission_status_id",
|
||||
"cv", "name", "phone", "email", "birthday", "info",
|
||||
).From(submissionsTable).
|
||||
Limit(request.PageSize).
|
||||
Offset(countOffset(request.Page, request.PageSize))
|
||||
|
||||
if request.Filters != nil {
|
||||
if request.Filters.AgentId != nil {
|
||||
getSubmissions = getSubmissions.Where(squirrel.Eq{"uid": *request.Filters.AgentId})
|
||||
}
|
||||
|
||||
if request.Filters.VacancyId != nil {
|
||||
getSubmissions = getSubmissions.Where(squirrel.Eq{"vacancy_id": *request.Filters.VacancyId})
|
||||
}
|
||||
|
||||
if request.Filters.Status != nil && *request.Filters.Status != dbtypes.SubStatusUnspecified {
|
||||
getSubmissions = getSubmissions.Where(squirrel.Eq{"submission_status_id": SubmissionStatusStringToId(*request.Filters.Status)})
|
||||
}
|
||||
}
|
||||
|
||||
query, args, err := getSubmissions.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building get submissions query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rows, err := c.db.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing get submissions query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
submissionsList := &dbtypes.SubmissionListGetResponse{
|
||||
Submissions: make([]dbtypes.Submission, 0, request.PageSize),
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
cvLink, info sql.NullString
|
||||
statusId int32
|
||||
candidateName string
|
||||
|
||||
sub = dbtypes.Submission{
|
||||
AgentInfo: new(dbtypes.AgentInfo),
|
||||
VacancyInfo: new(dbtypes.VacancyInfo),
|
||||
CandidateInfo: new(dbtypes.CandidateInfo),
|
||||
}
|
||||
)
|
||||
|
||||
if err := rows.Scan(
|
||||
&sub.Id, &sub.AgentInfo.Id, &sub.VacancyInfo.Id, &statusId,
|
||||
&cvLink, &candidateName, &sub.CandidateInfo.PhoneNumber, &sub.CandidateInfo.Email,
|
||||
&sub.CandidateInfo.Birthday, &info,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
sub.CandidateInfo.LastName, sub.CandidateInfo.FirstName, sub.CandidateInfo.MiddleName = splitName(candidateName)
|
||||
|
||||
if cvLink.Valid {
|
||||
sub.CandidateInfo.CvLink = &cvLink.String
|
||||
}
|
||||
|
||||
if info.Valid {
|
||||
sub.CandidateInfo.Resume = &info.String
|
||||
}
|
||||
|
||||
sub.Status = SubmissionStatusIdToString(statusId)
|
||||
|
||||
submissionsList.Submissions = append(submissionsList.Submissions, sub)
|
||||
}
|
||||
|
||||
return submissionsList, nil
|
||||
}
|
||||
|
||||
func splitName(name string) (string, string, string) {
|
||||
var (
|
||||
parts = strings.SplitN(name, " ", 3)
|
||||
lastName, firstName, middleName string
|
||||
)
|
||||
|
||||
if len(parts) > 0 {
|
||||
lastName = parts[0]
|
||||
}
|
||||
|
||||
if len(parts) > 1 {
|
||||
firstName = parts[1]
|
||||
}
|
||||
|
||||
if len(parts) > 2 {
|
||||
middleName = parts[2]
|
||||
}
|
||||
|
||||
return lastName, firstName, middleName
|
||||
}
|
||||
|
||||
func (c *client) CreateSubmission(
|
||||
ctx context.Context,
|
||||
request *dbtypes.SubmissionCreateRequest,
|
||||
) (*dbtypes.SubmissionCreateResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
if request.CandidateInfo == nil {
|
||||
return nil, fmt.Errorf("%w: request.CandidateInfo is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
submissionsTable = fmt.Sprintf("%s.%s", c.config.Schema, SubmissionsTableName)
|
||||
)
|
||||
|
||||
var (
|
||||
// TODO: use normal uuid after DB reengineering
|
||||
subId = fmt.Sprintf("%sSUB", strings.ReplaceAll(uuid.NewString(), "-", ""))
|
||||
fullName = formatName(request.CandidateInfo.LastName, request.CandidateInfo.FirstName, request.CandidateInfo.MiddleName)
|
||||
)
|
||||
|
||||
createSubmission := psql.Insert(submissionsTable).
|
||||
Columns(
|
||||
"id", "uid", "vacancy_id", "submission_status_id",
|
||||
"cv", "name", "phone", "email", "birthday", "info",
|
||||
).
|
||||
Values(
|
||||
subId, request.AgentId, request.VacancyId, SubmissionStatusStringToId(dbtypes.SubStatusNew),
|
||||
request.CandidateInfo.CvLink, fullName, request.CandidateInfo.PhoneNumber,
|
||||
request.CandidateInfo.Email, request.CandidateInfo.Birthday, request.CandidateInfo.Resume,
|
||||
)
|
||||
|
||||
query, args, err := createSubmission.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building create submission query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := c.db.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing create submission query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for create submission query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return &dbtypes.SubmissionCreateResponse{
|
||||
Id: subId,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NOTE: lastName and firstName are required to be non-empty
|
||||
func formatName(lastName, firstName, middleName string) string {
|
||||
name := fmt.Sprintf("%s %s", lastName, firstName)
|
||||
|
||||
if middleName != "" {
|
||||
name = fmt.Sprintf("%s %s", name, middleName)
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
//nolint:funlen,gocognit // TODO: refactor
|
||||
func (c *client) UpdateSubmissionStatus(
|
||||
ctx context.Context,
|
||||
request *dbtypes.SubmissionStatusUpdateRequest,
|
||||
) (*dbtypes.SubmissionStatusUpdateResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
submissionsTable = fmt.Sprintf("%s.%s", c.config.Schema, SubmissionsTableName)
|
||||
)
|
||||
|
||||
updateSubmissionStatus := psql.Update(submissionsTable).
|
||||
Set("submission_status_id", SubmissionStatusStringToId(request.Status)).
|
||||
Where(squirrel.Eq{"id": request.Id})
|
||||
|
||||
query, args, err := updateSubmissionStatus.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building 'update submission status' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if request.Status != dbtypes.SubStatusApproved {
|
||||
res, err := c.db.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing 'update submission status' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for 'update submission status' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return &dbtypes.SubmissionStatusUpdateResponse{}, nil
|
||||
}
|
||||
|
||||
tx, err := c.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error starting transaction: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
vacancy, agentId, err := c.getSubmissionMetadata(ctx, tx, request.Id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting vacancy info: %w", err)
|
||||
}
|
||||
|
||||
if vacancy.AgentReward == nil {
|
||||
return nil, fmt.Errorf("%w: agent reward is unknown", dberrors.ErrForbidden)
|
||||
}
|
||||
|
||||
if vacancy.IsArchived {
|
||||
return nil, fmt.Errorf("%w: vacancy is closed", dberrors.ErrForbidden)
|
||||
}
|
||||
|
||||
if vacancy.CurrentCandidates+1 > vacancy.RequiredCandidates {
|
||||
return nil, fmt.Errorf("%w: vacancy quota exceeded", dberrors.ErrForbidden)
|
||||
}
|
||||
|
||||
if err := c.addSubmissionCandidate(ctx, tx, vacancy.Id); err != nil {
|
||||
return nil, fmt.Errorf("%w: error adding submission candidate: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
payload := dbtypes.TransactionPayload{
|
||||
Origin: "submission",
|
||||
CompanyId: vacancy.Company.Id,
|
||||
CompanyName: vacancy.Company.Name,
|
||||
VacancyId: vacancy.Id,
|
||||
VacancyName: vacancy.Name,
|
||||
}
|
||||
|
||||
molvaAgentTransId := uuid.NewString()
|
||||
|
||||
if _, err := c.createTransactionWithDriver(ctx, tx, &dbtypes.TransactionCreateRequest{
|
||||
OwnerId: agentId,
|
||||
Amount: int64(*vacancy.AgentReward),
|
||||
Currency: "RUB",
|
||||
RequestId: molvaAgentTransId,
|
||||
Payload: &payload,
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("error creating molva -> agent transaction: %w", err)
|
||||
}
|
||||
|
||||
distMolvaTransId := uuid.NewString()
|
||||
|
||||
if _, err := c.createTransactionWithDriver(ctx, tx, &dbtypes.TransactionCreateRequest{
|
||||
OwnerId: vacancy.Company.Id,
|
||||
Amount: -int64(*vacancy.AgentReward),
|
||||
Currency: "RUB",
|
||||
RequestId: distMolvaTransId,
|
||||
Payload: &payload,
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("error creating dist -> molva transaction: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, fmt.Errorf("%w: error committing transaction: %w", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := tx.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing 'update submission status' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for 'update submission status' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return &dbtypes.SubmissionStatusUpdateResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *client) getSubmissionMetadata(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
submissionId string,
|
||||
) (*dbtypes.Vacancy, string, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
submissionsTable = fmt.Sprintf("%s.%s s", c.config.Schema, SubmissionsTableName)
|
||||
companiesTable = fmt.Sprintf("%s.%s c", c.config.Schema, CompaniesTableName)
|
||||
vacanciesTable = fmt.Sprintf("%s.%s v", c.config.Schema, VacanciesTableName)
|
||||
vacancyCandidatesTable = fmt.Sprintf("%s.%s vc", c.config.Schema, VacancyCandidatesTableName)
|
||||
)
|
||||
|
||||
getMetadata := psql.Select(
|
||||
"s.uid", "v.id", "v.name", "v.company_id", "c.name", "v.agent_reward", "v.is_archived",
|
||||
"vc.current_candidates_amt", "vc.required_candidates_amt",
|
||||
).From(submissionsTable).
|
||||
InnerJoin(fmt.Sprintf("%s on s.vacancy_id = v.id", vacanciesTable)).
|
||||
InnerJoin(fmt.Sprintf("%s on v.id = vc.vacancy_id", vacancyCandidatesTable)).
|
||||
InnerJoin(fmt.Sprintf("%s on v.company_id = c.id", companiesTable)).
|
||||
Where(squirrel.Eq{"s.id": submissionId}).
|
||||
Suffix("FOR UPDATE OF vc")
|
||||
|
||||
query, args, err := getMetadata.ToSql()
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("%w: error building 'get submission metadata' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := driver.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var (
|
||||
agentId string
|
||||
vacancy dbtypes.Vacancy
|
||||
)
|
||||
|
||||
if err := row.Scan(
|
||||
&agentId,
|
||||
&vacancy.Id, &vacancy.Name, &vacancy.Company.Id, &vacancy.Company.Name,
|
||||
&vacancy.AgentReward, &vacancy.IsArchived,
|
||||
&vacancy.CurrentCandidates, &vacancy.RequiredCandidates,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, "", dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, "", fmt.Errorf("%w: error scanning row for 'get submission metadata' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
return &vacancy, agentId, nil
|
||||
}
|
||||
|
||||
func (c *client) addSubmissionCandidate(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
vacancyId string,
|
||||
) error {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
vacancyCandisTable = fmt.Sprintf("%s.%s", c.config.Schema, VacancyCandidatesTableName)
|
||||
)
|
||||
|
||||
addSubmissionCandidate := psql.Update(vacancyCandisTable).
|
||||
Set("current_candidates_amt", squirrel.Expr("current_candidates_amt + 1")).
|
||||
Where(squirrel.Eq{"vacancy_id": vacancyId})
|
||||
|
||||
query, args, err := addSubmissionCandidate.ToSql()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error building 'add submission candidate' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error executing 'add submission candidate' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error getting rows affected for 'add submission candidate' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *client) DeleteSubmission(
|
||||
ctx context.Context,
|
||||
request *dbtypes.SubmissionDeleteRequest,
|
||||
) (*dbtypes.SubmissionDeleteResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
submissionsTable = fmt.Sprintf("%s.%s", c.config.Schema, SubmissionsTableName)
|
||||
)
|
||||
|
||||
deleteSubmission := psql.Update(submissionsTable).
|
||||
Set("submission_status_id", SubmissionStatusStringToId(dbtypes.SubStatusCancelled)).
|
||||
Where(squirrel.Eq{"id": request.Id})
|
||||
|
||||
query, args, err := deleteSubmission.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building delete submission query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := c.db.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing delete submission query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for delete submission query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return &dbtypes.SubmissionDeleteResponse{}, nil
|
||||
}
|
||||
485
internal/database/postgres/transaction.go
Normal file
@@ -0,0 +1,485 @@
|
||||
package pgdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
"github.com/Masterminds/squirrel"
|
||||
)
|
||||
|
||||
func getTransactionTypeByAmount(amount int64) dbtypes.TransactionType {
|
||||
if amount > 0 {
|
||||
return dbtypes.TransactionTypeDeposit
|
||||
}
|
||||
|
||||
return dbtypes.TransactionTypeWithdrawal
|
||||
}
|
||||
|
||||
// TODO: add migration to rebind statuses
|
||||
|
||||
func TransactionStatusIdToString(status int32) dbtypes.TransactionStatus {
|
||||
switch status {
|
||||
case 0:
|
||||
return dbtypes.TransactionStatusPending
|
||||
case 1:
|
||||
return dbtypes.TransactionStatusApproved
|
||||
case 2:
|
||||
return dbtypes.TransactionStatusRejected
|
||||
case 3:
|
||||
return dbtypes.TransactionStatusNew
|
||||
default:
|
||||
return dbtypes.TransactionStatusPending
|
||||
}
|
||||
}
|
||||
|
||||
func TransactionStatusStringToId(status dbtypes.TransactionStatus) int32 {
|
||||
switch status {
|
||||
case dbtypes.TransactionStatusNew:
|
||||
return 3
|
||||
case dbtypes.TransactionStatusPending:
|
||||
return 0
|
||||
case dbtypes.TransactionStatusApproved:
|
||||
return 1
|
||||
case dbtypes.TransactionStatusRejected:
|
||||
return 2
|
||||
default:
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:gocognit // not so hard
|
||||
func (c *client) GetTransactionList(
|
||||
ctx context.Context,
|
||||
request *dbtypes.TransactionListGetRequest,
|
||||
) (*dbtypes.TransactionListGetResponse, error) {
|
||||
if request == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
transactionsTable = fmt.Sprintf("%s.%s", c.config.Schema, TransactionsTableName)
|
||||
)
|
||||
|
||||
getTransactions := psql.Select(
|
||||
"id", "owner_id", "bank_account_id", "amount", "currency", "status", "created_at", "payload",
|
||||
).From(transactionsTable).
|
||||
Where(squirrel.Eq{"owner_id": request.OwnerId}).
|
||||
Limit(request.PageSize).
|
||||
Offset(countOffset(request.Page, request.PageSize))
|
||||
|
||||
getTransactions, err := c.setGetTransactionsQueryFilters(getTransactions, request.Filters)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error setting get transactions query filters: %v", dberrors.ErrBadRequest, err)
|
||||
}
|
||||
|
||||
query, args, err := getTransactions.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building get transactions query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rows, err := c.db.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing get transactions query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
transList := &dbtypes.TransactionListGetResponse{
|
||||
Transactions: make([]dbtypes.Transaction, 0, request.PageSize),
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
transStatus int32
|
||||
ownerId string
|
||||
payload, bankAccountId sql.NullString
|
||||
transaction dbtypes.Transaction
|
||||
)
|
||||
|
||||
if err := rows.Scan(
|
||||
&transaction.Id, &ownerId, &bankAccountId, &transaction.Amount, &transaction.Currency,
|
||||
&transStatus, &transaction.CreatedAt, &payload,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if bankAccountId.Valid {
|
||||
bankAccountInfo, err := c.getBankAccountInfoById(ctx, c.db, bankAccountId.String)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting bank account info: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
transaction.BankAccountInfo = bankAccountInfo
|
||||
|
||||
ownerInfo, err := c.getOwnerInfoById(ctx, c.db, ownerId, bankAccountInfo.OwnerType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting owner info: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
transaction.OwnerInfo = ownerInfo
|
||||
}
|
||||
|
||||
transaction.Type = getTransactionTypeByAmount(transaction.Amount)
|
||||
transaction.Status = TransactionStatusIdToString(transStatus)
|
||||
|
||||
if payload.Valid {
|
||||
var payloadData dbtypes.TransactionPayload
|
||||
|
||||
if err := json.Unmarshal([]byte(payload.String), &payloadData); err != nil {
|
||||
return nil, fmt.Errorf("%w: error unmarshaling transaction payload: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
transaction.Payload = &payloadData
|
||||
}
|
||||
|
||||
transList.Transactions = append(transList.Transactions, transaction)
|
||||
}
|
||||
|
||||
return transList, nil
|
||||
}
|
||||
|
||||
func (c *client) setGetTransactionsQueryFilters(
|
||||
query squirrel.SelectBuilder,
|
||||
filters *dbtypes.TransactionListFilters,
|
||||
) (squirrel.SelectBuilder, error) {
|
||||
if filters == nil {
|
||||
return query, nil
|
||||
}
|
||||
|
||||
if filters.Type != nil {
|
||||
switch *filters.Type {
|
||||
case dbtypes.TransactionTypeDeposit:
|
||||
query = query.Where(squirrel.Gt{
|
||||
"amount": 0,
|
||||
})
|
||||
|
||||
case dbtypes.TransactionTypeWithdrawal:
|
||||
query = query.Where(squirrel.Lt{
|
||||
"amount": 0,
|
||||
})
|
||||
|
||||
default:
|
||||
return query, fmt.Errorf("%w: invalid transaction type: %v", dberrors.ErrBadRequest, *filters.Type)
|
||||
}
|
||||
}
|
||||
|
||||
if filters.Status != nil {
|
||||
query = query.Where(squirrel.Eq{"status": TransactionStatusStringToId(*filters.Status)})
|
||||
}
|
||||
|
||||
if filters.BankAccountId != nil {
|
||||
query = query.Where(squirrel.Eq{"bank_account_id": *filters.BankAccountId})
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
func (c *client) getOwnerInfoById(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
ownerId string,
|
||||
ownerType string,
|
||||
) (*dbtypes.TransactionOwnerInfo, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
clientTableName = fmt.Sprintf("%s.%s", c.config.Schema, UsersTableName)
|
||||
companyTableName = fmt.Sprintf("%s.%s", c.config.Schema, CompaniesTableName)
|
||||
)
|
||||
|
||||
var getOwnerInfoById squirrel.SelectBuilder
|
||||
|
||||
// TODO: reingeneer the DB
|
||||
switch ownerType {
|
||||
case "agent":
|
||||
getOwnerInfoById = psql.Select(
|
||||
"uid",
|
||||
"name",
|
||||
).
|
||||
From(clientTableName).
|
||||
Where(squirrel.Eq{"uid": ownerId})
|
||||
|
||||
case "company":
|
||||
getOwnerInfoById = psql.Select(
|
||||
"id",
|
||||
"name",
|
||||
).
|
||||
From(companyTableName).
|
||||
Where(squirrel.Eq{"id": ownerId})
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: invalid owner type", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
query, args, err := getOwnerInfoById.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building get owner info by id query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := driver.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var ownerInfo dbtypes.TransactionOwnerInfo
|
||||
|
||||
if err := row.Scan(
|
||||
&ownerInfo.Id,
|
||||
&ownerInfo.Name,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row for get owner info by id query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
return &ownerInfo, nil
|
||||
}
|
||||
|
||||
func (c *client) getBankAccountInfoById(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
bankAccountId string,
|
||||
) (*dbtypes.BankAccountInfo, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
bankAccountsTableName = fmt.Sprintf("%s.%s", c.config.Schema, BankAccountsTableName)
|
||||
)
|
||||
|
||||
getBankAccountInfoById := psql.Select(
|
||||
"id",
|
||||
"account_number",
|
||||
"bank_name",
|
||||
"bik",
|
||||
"correspondent_account",
|
||||
"owner_type",
|
||||
).
|
||||
From(bankAccountsTableName).
|
||||
Where(squirrel.Eq{"id": bankAccountId})
|
||||
|
||||
query, args, err := getBankAccountInfoById.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building get bank account info by id query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := driver.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var accountInfo dbtypes.BankAccountInfo
|
||||
|
||||
if err := row.Scan(
|
||||
&accountInfo.Id,
|
||||
&accountInfo.AccountNumber,
|
||||
&accountInfo.BankName,
|
||||
&accountInfo.Bik,
|
||||
&accountInfo.CorrespondentAccount,
|
||||
&accountInfo.OwnerType,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row for get bank account info by id query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
return &accountInfo, nil
|
||||
}
|
||||
|
||||
func (c *client) CreateTransaction(
|
||||
ctx context.Context,
|
||||
request *dbtypes.TransactionCreateRequest,
|
||||
) (*dbtypes.TransactionCreateResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := c.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error starting transaction: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
result, err := c.createTransactionWithDriver(ctx, tx, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating transaction: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, fmt.Errorf("%w: error committing transaction: %w", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *client) createTransactionWithDriver(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
request *dbtypes.TransactionCreateRequest,
|
||||
) (*dbtypes.TransactionCreateResponse, error) {
|
||||
if _, err := c.getRawBalanceForUpdate(ctx, driver, request.OwnerId); err != nil {
|
||||
return nil, fmt.Errorf("error getting raw balance for update: %w", err)
|
||||
}
|
||||
|
||||
result, err := c.createTransaction(ctx, driver, request)
|
||||
if err != nil {
|
||||
if errors.Is(err, dberrors.ErrConflict) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("error creating transaction: %w", err)
|
||||
}
|
||||
|
||||
if err := c.updateBalance(ctx, driver, request.Amount, request.OwnerId); err != nil {
|
||||
return nil, fmt.Errorf("error updating balance: %w", err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *client) getRawBalanceForUpdate(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
ownerId string,
|
||||
) (int64, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
balancesTable = fmt.Sprintf("%s.%s", c.config.Schema, BalancesTableName)
|
||||
)
|
||||
|
||||
getBalance := psql.Select(
|
||||
"raw_balance",
|
||||
).From(balancesTable).
|
||||
Where(squirrel.Eq{"owner_id": ownerId}).
|
||||
Suffix("FOR UPDATE")
|
||||
|
||||
query, args, err := getBalance.ToSql()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("%w: error building 'get balance' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := driver.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var rawBalance int64
|
||||
|
||||
if err := row.Scan(&rawBalance); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return 0, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
return rawBalance, nil
|
||||
}
|
||||
|
||||
func (c *client) updateBalance(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
amountDelta int64,
|
||||
ownerId string,
|
||||
) error {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
balancesTable = fmt.Sprintf("%s.%s", c.config.Schema, BalancesTableName)
|
||||
)
|
||||
|
||||
updateBalance := psql.Update(balancesTable).
|
||||
SetMap(map[string]any{
|
||||
"raw_balance": squirrel.Expr("raw_balance + ?", amountDelta),
|
||||
"updated_at": squirrel.Expr("NOW()"),
|
||||
}).
|
||||
Where(squirrel.Eq{"owner_id": ownerId})
|
||||
|
||||
query, args, err := updateBalance.ToSql()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error building 'update balance' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error executing 'update balance' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error getting rows affected for 'update balance' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *client) createTransaction(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
request *dbtypes.TransactionCreateRequest,
|
||||
) (*dbtypes.TransactionCreateResponse, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
transactionsTable = fmt.Sprintf("%s.%s", c.config.Schema, TransactionsTableName)
|
||||
)
|
||||
|
||||
var payload []byte
|
||||
|
||||
if request.Payload == nil {
|
||||
payload = []byte("{}")
|
||||
} else {
|
||||
payloadBytes, err := json.Marshal(request.Payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error marshaling transaction payload: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
payload = payloadBytes
|
||||
}
|
||||
|
||||
createTransaction := psql.Insert(transactionsTable).
|
||||
Columns(
|
||||
"id", "owner_id", "bank_account_id", "amount", "currency", "status", "created_at", "payload",
|
||||
).
|
||||
Values(
|
||||
request.RequestId, request.OwnerId, request.BankAccountId, request.Amount, request.Currency,
|
||||
dbtypes.TransactionStatusNew, squirrel.Expr("CURRENT_TIMESTAMP"), payload,
|
||||
).
|
||||
Suffix("ON CONFLICT (id, owner_id) DO NOTHING")
|
||||
|
||||
query, args, err := createTransaction.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building 'create transaction' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing 'create transaction' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for 'create transaction' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return &dbtypes.TransactionCreateResponse{
|
||||
Id: request.RequestId,
|
||||
}, dberrors.ErrConflict
|
||||
}
|
||||
|
||||
return &dbtypes.TransactionCreateResponse{
|
||||
Id: request.RequestId,
|
||||
}, nil
|
||||
}
|
||||
203
internal/database/postgres/user.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package pgdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func (c *client) GetClientValidation(
|
||||
ctx context.Context,
|
||||
request *dbtypes.ClientValidationGetRequest,
|
||||
) (*dbtypes.ClientValidationGetResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
userValidationTable = fmt.Sprintf("%s.%s", c.config.Schema, UserValidationTableName)
|
||||
)
|
||||
|
||||
getUserValidation := psql.Select(
|
||||
"status", "description",
|
||||
).
|
||||
From(userValidationTable).
|
||||
Where(squirrel.Eq{"uid": request.UserId})
|
||||
|
||||
query, args, err := getUserValidation.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building 'get user validation' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := c.db.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var result dbtypes.ClientValidation
|
||||
|
||||
if err := row.Scan(&result.Status, &result.Description); err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row for 'get user validation' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
return &dbtypes.ClientValidationGetResponse{
|
||||
ClientValidation: &result,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *client) CreateUser(
|
||||
ctx context.Context,
|
||||
request *dbtypes.UserSaveRequest,
|
||||
) (*dbtypes.UserSaveResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := c.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error starting transaction: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
result, err := c.createUser(ctx, tx, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating user: %w", err)
|
||||
}
|
||||
|
||||
if err := c.createUserValidationTicket(ctx, tx, request); err != nil {
|
||||
return nil, fmt.Errorf("error creating user validation ticket: %w", err)
|
||||
}
|
||||
|
||||
resp, err := c.createCompany(ctx, tx, &dbtypes.CompanyCreateRequest{
|
||||
OwnerId: request.Id,
|
||||
Staff: []string{
|
||||
request.Id,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating company: %w", err)
|
||||
}
|
||||
|
||||
var ownerId string
|
||||
|
||||
switch request.Type {
|
||||
case dbtypes.UserTypeAgent:
|
||||
ownerId = request.Id
|
||||
case dbtypes.UserTypeDistributor:
|
||||
ownerId = resp.Id
|
||||
default:
|
||||
return nil, fmt.Errorf("%w: unknown user type: %v", dberrors.ErrBadRequest, request.Type)
|
||||
}
|
||||
|
||||
balanceId := fmt.Sprintf("%sBAL", strings.ReplaceAll(uuid.NewString(), "-", ""))
|
||||
|
||||
if err := c.createBalance(ctx, tx, &dbtypes.BalanceCreateRequest{
|
||||
Id: balanceId,
|
||||
OwnerId: ownerId,
|
||||
RawBalance: 0,
|
||||
CleanBalance: 0,
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("error creating balance: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, fmt.Errorf("%w: error committing transaction: %w", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *client) createUser(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
request *dbtypes.UserSaveRequest,
|
||||
) (*dbtypes.UserSaveResponse, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
userTable = fmt.Sprintf("%s.%s", c.config.Schema, UsersTableName)
|
||||
)
|
||||
|
||||
saveUser := psql.Insert(userTable).
|
||||
Columns(
|
||||
"uid", "name", "phone", "email", "client_type_id",
|
||||
).
|
||||
Values(
|
||||
request.Id, request.FullName, request.Phone, request.Email, request.Type,
|
||||
)
|
||||
|
||||
query, args, err := saveUser.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building 'save user' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing 'save user' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for 'save user' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return &dbtypes.UserSaveResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *client) createUserValidationTicket(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
request *dbtypes.UserSaveRequest,
|
||||
) error {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
userValidationTable = fmt.Sprintf("%s.%s", c.config.Schema, UserValidationTableName)
|
||||
)
|
||||
|
||||
// TODO: use normal uuid after DB reengineering
|
||||
ticketId := fmt.Sprintf("%sVAL", strings.ReplaceAll(uuid.NewString(), "-", ""))
|
||||
|
||||
createUserValidation := psql.Insert(userValidationTable).
|
||||
Columns(
|
||||
"id", "uid", "status", "description", "last_update",
|
||||
).
|
||||
Values(
|
||||
ticketId, request.Id, dbtypes.ClientValStatusNew, request.FullName, squirrel.Expr("CURRENT_TIMESTAMP"),
|
||||
)
|
||||
|
||||
query, args, err := createUserValidation.ToSql()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error building 'create user validation' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error executing 'create user validation' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: error getting rows affected for 'create user validation' query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
573
internal/database/postgres/vacancy.go
Normal file
@@ -0,0 +1,573 @@
|
||||
package pgdb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func VacancyStatusIdToString(status int32) dbtypes.VacancyStatus {
|
||||
switch status {
|
||||
case 0:
|
||||
return dbtypes.VacUnspecified
|
||||
case 1:
|
||||
return dbtypes.VacNew
|
||||
case 2:
|
||||
return dbtypes.VacPending
|
||||
case 3:
|
||||
return dbtypes.VacApproved
|
||||
case 4:
|
||||
return dbtypes.VacRejected
|
||||
default:
|
||||
return dbtypes.VacUnspecified
|
||||
}
|
||||
}
|
||||
|
||||
func VacancyStatusStringToId(status dbtypes.VacancyStatus) int32 {
|
||||
switch status {
|
||||
case dbtypes.VacUnspecified:
|
||||
return 0
|
||||
case dbtypes.VacNew:
|
||||
return 1
|
||||
case dbtypes.VacPending:
|
||||
return 2
|
||||
case dbtypes.VacApproved:
|
||||
return 3
|
||||
case dbtypes.VacRejected:
|
||||
return 4
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:funlen,gocognit // maybe refactor later
|
||||
func (c *client) GetVacancyList(
|
||||
ctx context.Context,
|
||||
request *dbtypes.VacancyListGetRequest,
|
||||
) (*dbtypes.VacancyListGetResponse, error) {
|
||||
if request == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
vacancyTable = fmt.Sprintf("%s.%s v", c.config.Schema, VacanciesTableName)
|
||||
companyTable = fmt.Sprintf("%s.%s c", c.config.Schema, CompaniesTableName)
|
||||
)
|
||||
|
||||
getVacList := psql.Select(
|
||||
"v.id", "v.company_id", "c.name", "v.name", "v.address", "v.work_format",
|
||||
"v.agent_reward", "v.region", "v.salary_top", "v.salary_bottom", "v.requirements",
|
||||
"v.responsibilities", "v.additional_info", "v.is_archived",
|
||||
"v.target_action", "v.target_action_amount", "v.publish_date",
|
||||
"v.moderation_status_id", "v.required_candidates", "v.current_candidates",
|
||||
"v.additional_fields",
|
||||
).
|
||||
From(vacancyTable).
|
||||
LeftJoin(fmt.Sprintf("%s on v.company_id = c.id", companyTable)).
|
||||
Limit(request.PageSize).
|
||||
Offset(countOffset(request.Page, request.PageSize))
|
||||
|
||||
getVacList = c.setVacancyListFilters(getVacList, request.Filters)
|
||||
|
||||
query, args, err := getVacList.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building get vacancy list query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rows, err := c.db.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing get vacancy list query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
var (
|
||||
res dbtypes.VacancyListGetResponse
|
||||
vacancyIds = make([]string, 0, request.PageSize)
|
||||
)
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
status int32
|
||||
agentReward sql.NullInt32
|
||||
comName, reqs, resps, extraInfo, extraFields sql.NullString
|
||||
vacancy dbtypes.Vacancy
|
||||
)
|
||||
|
||||
if err := rows.Scan(
|
||||
&vacancy.Id, &vacancy.Company.Id, &comName, &vacancy.Name, &vacancy.Address,
|
||||
&vacancy.WorkFormat, &agentReward, &vacancy.Region, &vacancy.SalaryTop, &vacancy.SalaryBottom,
|
||||
&reqs, &resps, &extraInfo, &vacancy.IsArchived, &vacancy.TargetAction.Action, &vacancy.TargetAction.Duration,
|
||||
&vacancy.CreatedAt, &status, &vacancy.RequiredCandidates, &vacancy.CurrentCandidates,
|
||||
&extraFields,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if agentReward.Valid {
|
||||
vacancy.AgentReward = &agentReward.Int32
|
||||
}
|
||||
|
||||
if comName.Valid {
|
||||
vacancy.Company.Name = comName.String
|
||||
}
|
||||
|
||||
if reqs.Valid {
|
||||
vacancy.Requirements = &reqs.String
|
||||
}
|
||||
|
||||
if resps.Valid {
|
||||
vacancy.Responsibilities = &resps.String
|
||||
}
|
||||
|
||||
if extraInfo.Valid {
|
||||
vacancy.ExtraInfo = &extraInfo.String
|
||||
}
|
||||
|
||||
if extraFields.Valid {
|
||||
vacancy.ExtraFields = &extraFields.String
|
||||
}
|
||||
|
||||
vacancy.Moderation.Status = VacancyStatusIdToString(status)
|
||||
|
||||
res.Vacancies = append(res.Vacancies, vacancy)
|
||||
vacancyIds = append(vacancyIds, vacancy.Id)
|
||||
}
|
||||
|
||||
descriptions, err := c.getVacancyModerationDescriptionHistory(ctx, c.db, vacancyIds)
|
||||
if err != nil {
|
||||
if errors.Is(err, dberrors.ErrNotFound) {
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("error getting descriptions for vacancies: %w", err)
|
||||
}
|
||||
|
||||
for i, vacancy := range res.Vacancies {
|
||||
res.Vacancies[i].Moderation.DescriptionHistory = descriptions[vacancy.Id]
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func (c *client) setVacancyListFilters(
|
||||
query squirrel.SelectBuilder,
|
||||
filters *dbtypes.VacancyListFilters,
|
||||
) squirrel.SelectBuilder {
|
||||
if filters.DistributorId != nil {
|
||||
query = query.Where(squirrel.Eq{"c.uid": *filters.DistributorId})
|
||||
}
|
||||
|
||||
if filters.CompanyId != nil {
|
||||
query = query.Where(squirrel.Eq{"v.company_id": *filters.CompanyId})
|
||||
}
|
||||
|
||||
if filters.VacancyId != nil {
|
||||
query = query.Where(squirrel.Eq{"v.id": *filters.VacancyId})
|
||||
}
|
||||
|
||||
if filters.Region != nil {
|
||||
query = query.Where(squirrel.Eq{"v.region": *filters.Region})
|
||||
}
|
||||
|
||||
if filters.SalaryBottom != nil {
|
||||
query = query.Where(squirrel.Or{
|
||||
squirrel.GtOrEq{"v.salary_bottom": *filters.SalaryBottom},
|
||||
squirrel.Eq{"v.salary_bottom": nil},
|
||||
})
|
||||
}
|
||||
|
||||
if filters.SalaryTop != nil {
|
||||
query = query.Where(squirrel.Or{
|
||||
squirrel.LtOrEq{"v.salary_top": *filters.SalaryTop},
|
||||
squirrel.Eq{"v.salary_top": nil},
|
||||
})
|
||||
}
|
||||
|
||||
if filters.IsArchived != nil {
|
||||
query = query.Where(squirrel.Eq{"v.is_archived": *filters.IsArchived})
|
||||
}
|
||||
|
||||
if filters.Status != nil {
|
||||
query = query.Where(squirrel.Eq{"v.moderation_status_id": VacancyStatusStringToId(*filters.Status)})
|
||||
}
|
||||
|
||||
return query
|
||||
}
|
||||
|
||||
func (c *client) getVacancyModerationDescriptionHistory(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
vacancyIds []string,
|
||||
) (map[string][]dbtypes.VacancyModerationDescription, error) {
|
||||
if len(vacancyIds) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
vacancyModerDescriptionsTable = fmt.Sprintf("%s.%s", c.config.Schema, VacancyDescriptionHistoryTableName)
|
||||
)
|
||||
|
||||
getVacancyModerationDescriptionHistory := psql.Select(
|
||||
"vacancy_id",
|
||||
"description",
|
||||
"created_at",
|
||||
).
|
||||
From(vacancyModerDescriptionsTable).
|
||||
Where(squirrel.Eq{"vacancy_id": vacancyIds}).
|
||||
OrderBy("vacancy_id", "created_at ASC")
|
||||
|
||||
query, args, err := getVacancyModerationDescriptionHistory.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building getVacancyModerationDescriptionHistory query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rows, err := driver.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing getVacancyModerationDescriptionHistory query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
descriptionsMap := make(map[string][]dbtypes.VacancyModerationDescription)
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
vacancyId string
|
||||
description dbtypes.VacancyModerationDescription
|
||||
)
|
||||
|
||||
if err := rows.Scan(
|
||||
&vacancyId,
|
||||
&description.Description,
|
||||
&description.CreatedAt,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w: error scanning row for getVacancyModerationDescriptionHistory: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
descriptionsMap[vacancyId] = append(descriptionsMap[vacancyId], description)
|
||||
}
|
||||
|
||||
return descriptionsMap, nil
|
||||
}
|
||||
|
||||
func (c *client) CreateVacancy(
|
||||
ctx context.Context,
|
||||
request *dbtypes.VacancyCreateRequest,
|
||||
) (*dbtypes.VacancyCreateResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
vacancyTable = fmt.Sprintf("%s.%s", c.config.Schema, VacanciesTableName)
|
||||
)
|
||||
|
||||
// TODO: use normal uuid after DB reengineering
|
||||
vacancyId := fmt.Sprintf("%sVAC", strings.ReplaceAll(uuid.NewString(), "-", ""))
|
||||
|
||||
createVacancy := psql.Insert(vacancyTable).
|
||||
Columns(
|
||||
"id", "company_id", "name", "address", "work_format", "agent_reward",
|
||||
"salary_top", "salary_bottom", "requirements", "responsibilities", "additional_info",
|
||||
"region", "is_archived", "target_action", "target_action_amount", "moderation_status_id",
|
||||
"required_candidates", "publish_date", "current_candidates", "additional_fields",
|
||||
).
|
||||
Values(
|
||||
vacancyId, request.CompanyId, request.Name, request.Address, request.WorkFormat, request.AgentReward,
|
||||
request.SalaryTop, request.SalaryBottom, request.Requirements, request.Responsibilities, request.ExtraInfo,
|
||||
request.Region, false, request.TargetAction.Action, request.TargetAction.Duration, VacancyStatusStringToId(dbtypes.VacNew),
|
||||
request.RequiredCandidates, squirrel.Expr("now()"), request.CurrentCandidates, request.ExtraFields,
|
||||
)
|
||||
|
||||
query, args, err := createVacancy.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building create vacancy query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := c.db.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
// TODO: process conflict via err.(*pq.Error).Code
|
||||
return nil, fmt.Errorf("%w: error executing create vacancy query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for create vacancy query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return &dbtypes.VacancyCreateResponse{Id: vacancyId}, nil
|
||||
}
|
||||
|
||||
func (c *client) UpdateVacancy(
|
||||
ctx context.Context,
|
||||
request *dbtypes.VacancyUpdateRequest,
|
||||
) (*dbtypes.VacancyUpdateResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
tx, err := c.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error starting transaction: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
status, err := c.getVacancyModerStatusForUpdate(ctx, tx, request.Id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting vacancy moder status: %w", err)
|
||||
}
|
||||
|
||||
if status == dbtypes.VacApproved {
|
||||
return nil, dberrors.ErrForbidden
|
||||
}
|
||||
|
||||
res, err := c.updateVacancy(ctx, tx, request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error updating vacancy: %w", err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, fmt.Errorf("error committing transaction: %w", err)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (c *client) getVacancyModerStatusForUpdate(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
vacancyId string,
|
||||
) (dbtypes.VacancyStatus, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
vacancyTable = fmt.Sprintf("%s.%s", c.config.Schema, VacanciesTableName)
|
||||
)
|
||||
|
||||
getVacancyModerStatus := psql.Select(
|
||||
"moderation_status_id",
|
||||
).
|
||||
From(vacancyTable).
|
||||
Where(squirrel.Eq{"id": vacancyId}).
|
||||
Suffix("FOR UPDATE")
|
||||
|
||||
query, args, err := getVacancyModerStatus.ToSql()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%w: error building get vacancy moder status query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
row := driver.QueryRowContext(ctx, query, args...)
|
||||
|
||||
var (
|
||||
statusId int32
|
||||
)
|
||||
|
||||
if err := row.Scan(&statusId); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return "", dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("%w: error scanning row for get vacancy moder status query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
return VacancyStatusIdToString(statusId), nil
|
||||
}
|
||||
|
||||
func (c *client) updateVacancy(
|
||||
ctx context.Context,
|
||||
driver Driver,
|
||||
request *dbtypes.VacancyUpdateRequest,
|
||||
) (*dbtypes.VacancyUpdateResponse, error) {
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
vacancyTable = fmt.Sprintf("%s.%s", c.config.Schema, VacanciesTableName)
|
||||
)
|
||||
|
||||
updateVacancy := psql.Update(vacancyTable).
|
||||
Where(squirrel.Eq{"id": request.Id})
|
||||
|
||||
if request.Name != nil {
|
||||
updateVacancy = updateVacancy.Set("name", *request.Name)
|
||||
}
|
||||
|
||||
if request.Address != nil {
|
||||
updateVacancy = updateVacancy.Set("address", *request.Address)
|
||||
}
|
||||
|
||||
if request.WorkFormat != nil {
|
||||
updateVacancy = updateVacancy.Set("work_format", *request.WorkFormat)
|
||||
}
|
||||
|
||||
if request.AgentReward != nil {
|
||||
updateVacancy = updateVacancy.Set("agent_reward", *request.AgentReward)
|
||||
}
|
||||
|
||||
if request.SalaryTop != nil {
|
||||
updateVacancy = updateVacancy.Set("salary_top", *request.SalaryTop)
|
||||
}
|
||||
|
||||
if request.SalaryBottom != nil {
|
||||
updateVacancy = updateVacancy.Set("salary_bottom", *request.SalaryBottom)
|
||||
}
|
||||
|
||||
if request.Requirements != nil {
|
||||
updateVacancy = updateVacancy.Set("requirements", *request.Requirements)
|
||||
}
|
||||
|
||||
if request.Responsibilities != nil {
|
||||
updateVacancy = updateVacancy.Set("responsibilities", *request.Responsibilities)
|
||||
}
|
||||
|
||||
if request.ExtraInfo != nil {
|
||||
updateVacancy = updateVacancy.Set("extra_info", *request.ExtraInfo)
|
||||
}
|
||||
|
||||
if request.Region != nil {
|
||||
updateVacancy = updateVacancy.Set("region", *request.Region)
|
||||
}
|
||||
|
||||
if request.TargetAction.Action != nil {
|
||||
updateVacancy = updateVacancy.Set("target_action", *request.TargetAction.Action)
|
||||
}
|
||||
|
||||
if request.TargetAction.Duration != nil {
|
||||
updateVacancy = updateVacancy.Set("target_action_amount", *request.TargetAction.Duration)
|
||||
}
|
||||
|
||||
if request.RequiredCandidates != nil {
|
||||
updateVacancy = updateVacancy.Set("required_candidates", *request.RequiredCandidates)
|
||||
}
|
||||
|
||||
if request.ExtraFields != nil {
|
||||
updateVacancy = updateVacancy.Set("additional_fields", *request.ExtraFields)
|
||||
}
|
||||
|
||||
query, args, err := updateVacancy.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building update vacancy query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := driver.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing update vacancy query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for update vacancy query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrInternal
|
||||
}
|
||||
|
||||
return &dbtypes.VacancyUpdateResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *client) DeleteVacancy(
|
||||
ctx context.Context,
|
||||
request *dbtypes.VacancyDeleteRequest,
|
||||
) (*dbtypes.VacancyDeleteResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
vacancyTable = fmt.Sprintf("%s.%s", c.config.Schema, VacanciesTableName)
|
||||
)
|
||||
|
||||
deleteVacancy := psql.Update(vacancyTable).
|
||||
Set("is_archived", true).
|
||||
Where(squirrel.Eq{"id": request.Id})
|
||||
|
||||
query, args, err := deleteVacancy.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building delete vacancy query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := c.db.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing delete vacancy query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for delete vacancy query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return &dbtypes.VacancyDeleteResponse{}, nil
|
||||
}
|
||||
|
||||
func (c *client) SendVacancyToModeration(
|
||||
ctx context.Context,
|
||||
request *dbtypes.SendVacancyToModerationRequest,
|
||||
) (*dbtypes.SendVacancyToModerationResponse, error) {
|
||||
if request == nil {
|
||||
return nil, fmt.Errorf("%w: request is nil", dberrors.ErrBadRequest)
|
||||
}
|
||||
|
||||
var (
|
||||
psql = squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar)
|
||||
|
||||
vacancyTable = fmt.Sprintf("%s.%s", c.config.Schema, VacanciesTableName)
|
||||
)
|
||||
|
||||
sendVacancyToModeration := psql.Update(vacancyTable).
|
||||
Set("moderation_status_id", VacancyStatusStringToId(dbtypes.VacPending)).
|
||||
Where(squirrel.Eq{"id": request.Id})
|
||||
|
||||
query, args, err := sendVacancyToModeration.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error building send vacancy to moderation query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
res, err := c.db.ExecContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error executing send vacancy to moderation query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: error getting rows affected for send vacancy to moderation query: %v", dberrors.ErrInternal, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
return nil, dberrors.ErrNotFound
|
||||
}
|
||||
|
||||
return &dbtypes.SendVacancyToModerationResponse{}, nil
|
||||
}
|
||||
217
internal/database/types/balance.go
Normal file
@@ -0,0 +1,217 @@
|
||||
package dbtypes
|
||||
|
||||
import "time"
|
||||
|
||||
type (
|
||||
Balance struct {
|
||||
RawBalance int64
|
||||
CleanBalance int64
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
BalanceGetRequest struct {
|
||||
OwnerId string
|
||||
}
|
||||
|
||||
BalanceGetResponse struct {
|
||||
Balance *Balance
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
BalanceCreateRequest struct {
|
||||
Id string
|
||||
OwnerId string
|
||||
RawBalance int64
|
||||
CleanBalance int64
|
||||
}
|
||||
)
|
||||
|
||||
type TransactionStatus string
|
||||
|
||||
const (
|
||||
TransactionStatusNew TransactionStatus = "new"
|
||||
TransactionStatusPending TransactionStatus = "pending"
|
||||
TransactionStatusApproved TransactionStatus = "approved"
|
||||
TransactionStatusRejected TransactionStatus = "rejected"
|
||||
)
|
||||
|
||||
func NewTransactionStatus(status *string) *TransactionStatus {
|
||||
if status == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := TransactionStatus(*status)
|
||||
|
||||
return &res
|
||||
}
|
||||
|
||||
type TransactionType string
|
||||
|
||||
const (
|
||||
TransactionTypeDeposit TransactionType = "deposit"
|
||||
TransactionTypeWithdrawal TransactionType = "withdrawal"
|
||||
)
|
||||
|
||||
func NewTransactionType(typ *string) *TransactionType {
|
||||
if typ == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := TransactionType(*typ)
|
||||
|
||||
return &res
|
||||
}
|
||||
|
||||
type (
|
||||
Transaction struct {
|
||||
Id string
|
||||
OwnerInfo *TransactionOwnerInfo
|
||||
BankAccountInfo *BankAccountInfo
|
||||
Type TransactionType
|
||||
Status TransactionStatus
|
||||
Amount int64
|
||||
Currency string
|
||||
CreatedAt time.Time
|
||||
Payload *TransactionPayload
|
||||
}
|
||||
|
||||
BankAccountInfo struct {
|
||||
Id string
|
||||
AccountNumber string
|
||||
AccountName string
|
||||
BankName string
|
||||
Bik string
|
||||
CorrespondentAccount string
|
||||
OwnerType string
|
||||
}
|
||||
|
||||
TransactionOwnerInfo struct {
|
||||
Id string
|
||||
Name string
|
||||
}
|
||||
|
||||
// TODO: make DB migration to use this
|
||||
// TransactionPayload struct {
|
||||
// Origin string `json:"origin"`
|
||||
// CompanyInfo *PayloadCompanyInfo `json:"company_info"`
|
||||
// VacancyInfo *PayloadVacancyInfo `json:"vacancy_info"`
|
||||
// }
|
||||
|
||||
// PayloadCompanyInfo struct {
|
||||
// Id string `json:"id"`
|
||||
// Name string `json:"name"`
|
||||
// }
|
||||
|
||||
// PayloadVacancyInfo struct {
|
||||
// Id string `json:"id"`
|
||||
// Name string `json:"name"`
|
||||
// }
|
||||
|
||||
TransactionPayload struct {
|
||||
Origin string `json:"origin"`
|
||||
CompanyId string `json:"company_id"`
|
||||
CompanyName string `json:"company_name"`
|
||||
VacancyId string `json:"vacancy_id"`
|
||||
VacancyName string `json:"vacancy_name"`
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
TransactionListGetRequest struct {
|
||||
OwnerId string
|
||||
Filters *TransactionListFilters
|
||||
Page uint64
|
||||
PageSize uint64
|
||||
}
|
||||
|
||||
TransactionListFilters struct {
|
||||
Type *TransactionType
|
||||
Status *TransactionStatus
|
||||
BankAccountId *string
|
||||
}
|
||||
|
||||
TransactionListGetResponse struct {
|
||||
Transactions []Transaction
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
TransactionCreateRequest struct {
|
||||
OwnerId string
|
||||
Amount int64
|
||||
Currency string
|
||||
BankAccountId *string
|
||||
RequestId string
|
||||
Payload *TransactionPayload
|
||||
}
|
||||
|
||||
TransactionCreateResponse struct {
|
||||
Id string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
BankAccount struct {
|
||||
Id string
|
||||
OwnerId string
|
||||
AccountNumber string
|
||||
AccountName string
|
||||
BankName string
|
||||
Bik string
|
||||
CorrespondentAccount string
|
||||
IsPrimary bool
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
BankAccountListGetRequest struct {
|
||||
OwnerId string
|
||||
}
|
||||
|
||||
BankAccountListGetResponse struct {
|
||||
BankAccounts []BankAccount
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
BankAccountCreateRequest struct {
|
||||
OwnerId string
|
||||
AccountNumber *string
|
||||
AccountName *string
|
||||
BankName *string
|
||||
Bik *string
|
||||
CorrespondentAccount *string
|
||||
IsPrimary *bool
|
||||
}
|
||||
|
||||
BankAccountCreateResponse struct {
|
||||
Id string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
BankAccountUpdateRequest struct {
|
||||
Id string
|
||||
AccountNumber *string
|
||||
AccountName *string
|
||||
BankName *string
|
||||
Bik *string
|
||||
CorrespondentAccount *string
|
||||
IsPrimary *bool
|
||||
}
|
||||
|
||||
BankAccountUpdateResponse struct{}
|
||||
)
|
||||
|
||||
type (
|
||||
BankAccountDeleteRequest struct {
|
||||
Id string
|
||||
OwnerId string
|
||||
}
|
||||
|
||||
BankAccountDeleteResponse struct{}
|
||||
)
|
||||
101
internal/database/types/company.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package dbtypes
|
||||
|
||||
type CompanyModerationStatus string
|
||||
|
||||
const (
|
||||
CompanyModerationStatusNew CompanyModerationStatus = "new"
|
||||
CompanyModerationStatusPending CompanyModerationStatus = "pending"
|
||||
CompanyModerationStatusApproved CompanyModerationStatus = "approved"
|
||||
CompanyModerationStatusRejected CompanyModerationStatus = "rejected"
|
||||
)
|
||||
|
||||
type (
|
||||
Company struct {
|
||||
Id string
|
||||
OwnerId string
|
||||
Name *string
|
||||
LegalPerson *string
|
||||
Description *string
|
||||
Website *string
|
||||
PhysicalAddress *string
|
||||
LegalAddress *string
|
||||
Inn *string
|
||||
Kpp *string
|
||||
IsActive bool
|
||||
HasModerationTicket bool
|
||||
Staff []string
|
||||
Metadata *string
|
||||
ExtraFieldsTemplate *string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
CompanyListGetRequest struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
CompanyListGetResponse struct {
|
||||
Companies []Company
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
CompanyByIdGetRequest struct {
|
||||
Id string
|
||||
CompanyId string
|
||||
}
|
||||
|
||||
CompanyByIdGetResponse struct {
|
||||
Company Company
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
CompanyCreateRequest struct {
|
||||
OwnerId string
|
||||
Name *string
|
||||
LegalPerson *string
|
||||
Description *string
|
||||
Website *string
|
||||
PhysicalAddress *string
|
||||
LegalAddress *string
|
||||
Inn *string
|
||||
Kpp *string
|
||||
Staff []string
|
||||
Metadata *string
|
||||
ExtraFieldsTemplate *string
|
||||
}
|
||||
|
||||
CompanyCreateResponse struct {
|
||||
Id string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
CompanyUpdateRequest struct {
|
||||
Id string
|
||||
Name *string
|
||||
LegalPerson *string
|
||||
Description *string
|
||||
Website *string
|
||||
PhysicalAddress *string
|
||||
LegalAddress *string
|
||||
Inn *string // can be updated in several rare cases
|
||||
Kpp *string // can be updated in several rare cases
|
||||
Staff []string
|
||||
Metadata *string
|
||||
ExtraFields *string
|
||||
}
|
||||
|
||||
CompanyUpdateResponse struct {
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
CompanyDeleteRequest struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
CompanyDeleteResponse struct {
|
||||
}
|
||||
)
|
||||
53
internal/database/types/integration.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package dbtypes
|
||||
|
||||
type Fieldtype string
|
||||
|
||||
type (
|
||||
CompanyMetadata map[string]string
|
||||
|
||||
ValidValue struct {
|
||||
DisplayName string `json:"display_name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
/*
|
||||
CompanyExtraFieldTemplate describes single
|
||||
additional field of company additional fields template
|
||||
*/
|
||||
CompanyExtraFieldTemplate struct {
|
||||
SystemName string `json:"system_name"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Type Fieldtype `json:"type"`
|
||||
Required bool `json:"required"`
|
||||
MultipleChoice bool `json:"multiple_choice"`
|
||||
ValidValues []ValidValue `json:"valid_values"`
|
||||
}
|
||||
|
||||
/*
|
||||
CompanyExtraFieldsTemplate describes additional fields
|
||||
needed to integrate company
|
||||
*/
|
||||
CompanyExtraFieldsTemplate struct {
|
||||
Fields []CompanyExtraFieldTemplate `json:"fields"`
|
||||
}
|
||||
|
||||
/*
|
||||
VacancyExtraFieldTemplate describes single filled
|
||||
additional field of vacancy additional fields template
|
||||
*/
|
||||
VacancyExtraFieldTemplate struct {
|
||||
SystemName string `json:"system_name"`
|
||||
Type Fieldtype `json:"type"`
|
||||
IsValidValue bool `json:"is_valid_values"`
|
||||
MultipleChoice bool `json:"multiple_choice"`
|
||||
Value []string `json:"value"`
|
||||
}
|
||||
|
||||
/*
|
||||
VacancyExtraFieldsTemplate describes additional fields
|
||||
filled during vacancy creation
|
||||
*/
|
||||
VacancyExtraFieldsTemplate struct {
|
||||
Fields []VacancyExtraFieldTemplate `json:"fields"`
|
||||
}
|
||||
)
|
||||
31
internal/database/types/profile.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package dbtypes
|
||||
|
||||
type (
|
||||
Profile struct {
|
||||
Id string
|
||||
Name string
|
||||
PhoneNumber string
|
||||
Email string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
ProfileGetRequest struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
ProfileGetResponse struct {
|
||||
Profile *Profile
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
ProfileUpdateRequest struct {
|
||||
Id string
|
||||
Name *string
|
||||
PhoneNumber *string
|
||||
Email *string
|
||||
}
|
||||
|
||||
ProfileUpdateResponse struct{}
|
||||
)
|
||||
100
internal/database/types/submission.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package dbtypes
|
||||
|
||||
type SubmissionStatus string
|
||||
|
||||
const (
|
||||
SubStatusUnspecified SubmissionStatus = "unspecified"
|
||||
SubStatusNew SubmissionStatus = "new"
|
||||
SubStatusPending SubmissionStatus = "pending"
|
||||
SubStatusOnInterview SubmissionStatus = "on_interview"
|
||||
SubStatusApproved SubmissionStatus = "approved"
|
||||
SubStatusCancelled SubmissionStatus = "cancelled"
|
||||
SubStatusRejected SubmissionStatus = "rejected"
|
||||
)
|
||||
|
||||
func NewSubmissionStatus(status *string) *SubmissionStatus {
|
||||
if status == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := SubmissionStatus(*status)
|
||||
|
||||
return &res
|
||||
}
|
||||
|
||||
type (
|
||||
Submission struct {
|
||||
Id string
|
||||
AgentInfo *AgentInfo
|
||||
VacancyInfo *VacancyInfo
|
||||
CandidateInfo *CandidateInfo
|
||||
Status SubmissionStatus
|
||||
}
|
||||
|
||||
AgentInfo struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
VacancyInfo struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
CandidateInfo struct {
|
||||
Id string
|
||||
FirstName string
|
||||
LastName string
|
||||
MiddleName string
|
||||
PhoneNumber string
|
||||
Email string
|
||||
Birthday string
|
||||
CvLink *string
|
||||
Resume *string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
SubmissionListGetRequest struct {
|
||||
Filters *SubmissionListGetFilters
|
||||
Page uint64
|
||||
PageSize uint64
|
||||
}
|
||||
|
||||
SubmissionListGetFilters struct {
|
||||
AgentId *string
|
||||
VacancyId *string
|
||||
Status *SubmissionStatus
|
||||
}
|
||||
|
||||
SubmissionListGetResponse struct {
|
||||
Submissions []Submission
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
SubmissionCreateRequest struct {
|
||||
AgentId string
|
||||
VacancyId string
|
||||
CandidateInfo *CandidateInfo
|
||||
}
|
||||
|
||||
SubmissionCreateResponse struct {
|
||||
Id string
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
SubmissionStatusUpdateRequest struct {
|
||||
Id string
|
||||
Status SubmissionStatus
|
||||
}
|
||||
|
||||
SubmissionStatusUpdateResponse struct{}
|
||||
)
|
||||
|
||||
type (
|
||||
SubmissionDeleteRequest struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
SubmissionDeleteResponse struct{}
|
||||
)
|
||||
57
internal/database/types/user.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package dbtypes
|
||||
|
||||
type ClientValidationStatus string
|
||||
|
||||
const (
|
||||
ClientValStatusNew ClientValidationStatus = "new"
|
||||
ClientValStatusPending ClientValidationStatus = "on review"
|
||||
ClientValStatusApproved ClientValidationStatus = "confirmed"
|
||||
ClientValStatusRejected ClientValidationStatus = "rejected"
|
||||
)
|
||||
|
||||
type (
|
||||
ClientValidation struct {
|
||||
Status ClientValidationStatus `json:"status"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
ClientValidationGetRequest struct {
|
||||
UserId string
|
||||
}
|
||||
|
||||
ClientValidationGetResponse struct {
|
||||
ClientValidation *ClientValidation `json:"moderation"`
|
||||
}
|
||||
)
|
||||
|
||||
type UserType int32
|
||||
|
||||
const (
|
||||
UserTypeAgent UserType = 0 // NOTE: no iota here
|
||||
UserTypeDistributor UserType = 1
|
||||
)
|
||||
|
||||
type (
|
||||
User struct {
|
||||
Id string
|
||||
FullName string
|
||||
Phone string
|
||||
Email string
|
||||
Type UserType
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
UserSaveRequest struct {
|
||||
Id string
|
||||
FullName string
|
||||
Phone string
|
||||
Email string
|
||||
Type UserType
|
||||
}
|
||||
|
||||
UserSaveResponse struct {
|
||||
}
|
||||
)
|
||||
184
internal/database/types/vacancy.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package dbtypes
|
||||
|
||||
import "time"
|
||||
|
||||
type VacancyStatus string
|
||||
|
||||
const (
|
||||
VacUnspecified VacancyStatus = "unspecified"
|
||||
VacNew VacancyStatus = "new"
|
||||
VacPending VacancyStatus = "pending"
|
||||
VacApproved VacancyStatus = "approved"
|
||||
VacRejected VacancyStatus = "rejected"
|
||||
)
|
||||
|
||||
func NewVacancyStatus(status *string) *VacancyStatus {
|
||||
if status == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
res := VacancyStatus(*status)
|
||||
|
||||
return &res
|
||||
}
|
||||
|
||||
// <=============================>
|
||||
// Common Vacancy types
|
||||
// <=============================>
|
||||
|
||||
type (
|
||||
Vacancy struct {
|
||||
Id string
|
||||
Company VacancyCompanyInfo
|
||||
Name string
|
||||
Address string
|
||||
WorkFormat string
|
||||
AgentReward *int32
|
||||
SalaryTop int32
|
||||
SalaryBottom int32
|
||||
Requirements *string
|
||||
Responsibilities *string
|
||||
ExtraInfo *string
|
||||
Region string
|
||||
IsArchived bool
|
||||
TargetAction VacancyTargetAction
|
||||
Moderation VacancyModeration
|
||||
RequiredCandidates int32
|
||||
CurrentCandidates int32
|
||||
ExtraFields *string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
VacancyCompanyInfo struct {
|
||||
Id string
|
||||
Name string
|
||||
LogoLink *string
|
||||
}
|
||||
|
||||
VacancyTargetAction struct {
|
||||
Action string
|
||||
Duration int32
|
||||
}
|
||||
|
||||
VacancyModeration struct {
|
||||
Status VacancyStatus
|
||||
DescriptionHistory []VacancyModerationDescription
|
||||
}
|
||||
|
||||
VacancyModerationDescription struct {
|
||||
Description *string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
)
|
||||
|
||||
// <=============================>
|
||||
// Get Vacancy List
|
||||
// <=============================>
|
||||
|
||||
type (
|
||||
VacancyListGetRequest struct {
|
||||
Filters *VacancyListFilters
|
||||
Page uint64
|
||||
PageSize uint64
|
||||
}
|
||||
|
||||
VacancyListFilters struct {
|
||||
DistributorId *string
|
||||
CompanyId *string
|
||||
VacancyId *string
|
||||
Region *string
|
||||
SalaryBottom *int32
|
||||
SalaryTop *int32
|
||||
IsArchived *bool
|
||||
Status *VacancyStatus
|
||||
}
|
||||
|
||||
VacancyListGetResponse struct {
|
||||
Vacancies []Vacancy
|
||||
}
|
||||
)
|
||||
|
||||
// <=============================>
|
||||
// Create Vacancy
|
||||
// <=============================>
|
||||
|
||||
type (
|
||||
VacancyCreateRequest struct {
|
||||
CompanyId string
|
||||
Name string
|
||||
Address string
|
||||
WorkFormat string
|
||||
AgentReward *int32
|
||||
SalaryTop int32
|
||||
SalaryBottom int32
|
||||
Requirements *string
|
||||
Responsibilities *string
|
||||
ExtraInfo *string
|
||||
Region string
|
||||
TargetAction VacancyTargetAction
|
||||
RequiredCandidates int32
|
||||
CurrentCandidates int32
|
||||
ExtraFields *string
|
||||
}
|
||||
|
||||
VacancyCreateResponse struct {
|
||||
Id string
|
||||
}
|
||||
)
|
||||
|
||||
// <=============================>
|
||||
// Update Vacancy
|
||||
// <=============================>
|
||||
|
||||
type (
|
||||
VacancyUpdateRequest struct {
|
||||
Id string
|
||||
Name *string
|
||||
Address *string
|
||||
WorkFormat *string
|
||||
AgentReward *int32
|
||||
SalaryTop *int32
|
||||
SalaryBottom *int32
|
||||
Requirements *string
|
||||
Responsibilities *string
|
||||
ExtraInfo *string
|
||||
Region *string
|
||||
TargetAction VacancyTargetActionForUpdate
|
||||
RequiredCandidates *int32
|
||||
ExtraFields *string
|
||||
}
|
||||
|
||||
VacancyTargetActionForUpdate struct {
|
||||
Action *string
|
||||
Duration *int32
|
||||
}
|
||||
|
||||
VacancyUpdateResponse struct {
|
||||
}
|
||||
)
|
||||
|
||||
// <=============================>
|
||||
// Delete Vacancy
|
||||
// <=============================>
|
||||
|
||||
type (
|
||||
VacancyDeleteRequest struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
VacancyDeleteResponse struct {
|
||||
}
|
||||
)
|
||||
|
||||
// <=============================>
|
||||
// Send Vacancy to Moderation
|
||||
// <=============================>
|
||||
|
||||
type (
|
||||
SendVacancyToModerationRequest struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
SendVacancyToModerationResponse struct {
|
||||
}
|
||||
)
|
||||
17
internal/feed/errors.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package feed
|
||||
|
||||
import "errors"
|
||||
|
||||
// Ошибки, связанные с валидацией входных данных
|
||||
var (
|
||||
// ErrCancellationReasonRequired Возвращается при попытке отмены события без указания причины
|
||||
ErrCancellationReasonRequired = errors.New("cancellation reason is required for feed event cancellation")
|
||||
// ErrAttachmentIDRequired Возвращается при попытке отмены события без указания Id вложения
|
||||
ErrAttachmentIDRequired = errors.New("attachment Id is required for feed event cancellation")
|
||||
// ErrUserIDRequired Возвращается при попытке отмены события без указания Id пользователя
|
||||
ErrUserIDRequired = errors.New("user Id cancellation is required for feed event cancellation")
|
||||
// ErrCreationInvalidData Возвращается при попытке создания события без указания Id пользователя, или типа события, или сообщения
|
||||
ErrCreationInvalidData = errors.New("invalid event data provided for creation (missing owner, type, or message)")
|
||||
|
||||
ErrNotFound = errors.New("not found")
|
||||
)
|
||||
9
internal/feed/filters.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package feed
|
||||
|
||||
type Filter struct {
|
||||
OwnerID string // Id пользователя
|
||||
EventTypes []EventType // Фильтр по типам событий
|
||||
Limit uint64 // Лимит записей
|
||||
Offset uint64 // Смещение
|
||||
ShowCancelled bool // Показывать отмененные
|
||||
}
|
||||
101
internal/feed/handlers.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package feed
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
Service *Service
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
func NewFeedHandler(logger *slog.Logger, service *Service) *Handler {
|
||||
return &Handler{
|
||||
Service: service,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) CreateEvent(ctx context.Context, event *Event) error {
|
||||
if event == nil {
|
||||
h.logger.Error("CreateEvent: empty event",
|
||||
slog.String("error", ErrCreationInvalidData.Error()))
|
||||
|
||||
return ErrCreationInvalidData
|
||||
}
|
||||
|
||||
h.logger.Debug("CreateEvent: Attempting to create event",
|
||||
slog.String("type", event.EventType.String()),
|
||||
slog.String("ownerID", event.OwnerId))
|
||||
|
||||
if event.OwnerId == "" || event.EventType == "" || event.Message == "" {
|
||||
h.logger.Error("CreateEvent: Validation error",
|
||||
slog.String("error", ErrCreationInvalidData.Error()),
|
||||
slog.String("type", event.EventType.String()),
|
||||
slog.String("ownerID", event.OwnerId),
|
||||
slog.String("message", event.Message),
|
||||
)
|
||||
|
||||
return ErrCreationInvalidData
|
||||
}
|
||||
|
||||
if err := h.Service.AddUserEvent(ctx, event); err != nil {
|
||||
h.logger.Error("CreateEvent: Service error",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("type", event.EventType.String()),
|
||||
slog.String("ownerID", event.OwnerId))
|
||||
|
||||
return fmt.Errorf("Error creating event: %w", err)
|
||||
}
|
||||
|
||||
h.logger.Debug("CreateEvent: Successfully created event",
|
||||
slog.String("eventID", event.Id),
|
||||
slog.String("type", event.EventType.String()),
|
||||
slog.String("ownerID", event.OwnerId))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) CancelEvent(ctx context.Context, attachmentId string, reason string) error {
|
||||
h.logger.Debug("CancelEvent: Attempting to cancel event",
|
||||
slog.String("attachmentID", attachmentId),
|
||||
)
|
||||
|
||||
if attachmentId == "" {
|
||||
h.logger.Error("CancelEvent: Validation error",
|
||||
slog.String("error", "attachment Id is required"))
|
||||
|
||||
return ErrAttachmentIDRequired
|
||||
}
|
||||
|
||||
if reason == "" {
|
||||
h.logger.Error("CancelEvent: Validation error",
|
||||
slog.String("error", "cancellation reason is required"),
|
||||
slog.String("attachmentID", attachmentId))
|
||||
|
||||
return ErrCancellationReasonRequired
|
||||
}
|
||||
|
||||
if err := h.Service.CancelEvents(ctx, attachmentId, reason); err != nil {
|
||||
h.logger.Error("CancelEvent: Service error",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("attachmentID", attachmentId))
|
||||
|
||||
return fmt.Errorf("error cancelling event: %w", err)
|
||||
}
|
||||
|
||||
h.logger.Debug("CancelEvent: Successfully cancelled event",
|
||||
slog.String("attachmentID", attachmentId))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) GetCompanyIdByUidTmp(ctx context.Context, ownerID string) ([]string, error) {
|
||||
return h.Service.GetCompanyIdsByUid(ctx, ownerID)
|
||||
}
|
||||
|
||||
func (h *Handler) GetAgentIdBySubmissionId(ctx context.Context, submissionId string) (string, error) {
|
||||
return h.Service.GetAgentIdBySubmissionId(ctx, submissionId)
|
||||
}
|
||||
91
internal/feed/models.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package feed
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
EventType string
|
||||
UserRole string
|
||||
Visibility string
|
||||
)
|
||||
|
||||
const (
|
||||
// User Roles
|
||||
RoleAgent UserRole = "agent"
|
||||
RoleDistributor UserRole = "distributor"
|
||||
|
||||
// Visibility Types
|
||||
VisibilityPublic Visibility = "public" // Показывается всем агентам(инициатор может быть только дистр)
|
||||
VisibilityPrivate Visibility = "private" // Показывается только инициатору события
|
||||
VisibilityCompanyWide Visibility = "company_wide" // Показывается всем в компании
|
||||
|
||||
// Event Types (Common)
|
||||
EventWelcome EventType = "welcome"
|
||||
EventNewCompanyMember EventType = "new_company_member"
|
||||
|
||||
// Users Events
|
||||
EventProfileChanged EventType = "profile_changed"
|
||||
EventCompanyCreated EventType = "company_created"
|
||||
EventCompanyChanged EventType = "company_changed"
|
||||
EventVacancyCreated EventType = "vacancy_created"
|
||||
EventVacancyChanged EventType = "vacancy_changed"
|
||||
EventVacancyModerationSent EventType = "vacancy_moderation_sent"
|
||||
EventSubmissionStatusChanged EventType = "submission_status_changed"
|
||||
EventTransactionCreated EventType = "transaction_created"
|
||||
EventBankAccountChanged EventType = "bank_details_changed"
|
||||
EventBankAccountCreated EventType = "bank_account_created"
|
||||
EventPostAnketa EventType = "post_anketa"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
Id string `json:"id" db:"id"`
|
||||
OwnerId string `json:"owner_id" db:"owner_id"`
|
||||
OwnerType UserRole `json:"owner_type" db:"owner_type"`
|
||||
Message string `json:"message" db:"message"`
|
||||
Visibility Visibility `json:"visibility" db:"visibility"`
|
||||
CompanyID *string `json:"company_id,omitempty"`
|
||||
EventType EventType `json:"event_type" db:"event_type"`
|
||||
Payload EventPayload `json:"payload" db:"payload"`
|
||||
IsCancelled bool `json:"is_cancelled" db:"is_cancelled"`
|
||||
CancellationReason *string `json:"cancellation_reason" db:"cancellation_reason"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
func (e EventType) String() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
func (u UserRole) String() string {
|
||||
return string(u)
|
||||
}
|
||||
|
||||
func (e *Event) processNullableFields(companyID, cancellationReason sql.NullString) {
|
||||
if companyID.Valid {
|
||||
e.CompanyID = &companyID.String
|
||||
}
|
||||
|
||||
if cancellationReason.Valid {
|
||||
e.CancellationReason = &cancellationReason.String
|
||||
}
|
||||
}
|
||||
|
||||
type EventPayload struct {
|
||||
AttachmentId string `json:"attachment_id" db:"attachment_id"`
|
||||
AttachmentType AttachmentType `json:"attachment_type" db:"attachment_type"`
|
||||
AdditionalReceiver string `json:"additional_receiver,omitempty" db:"additional_receiver"` // may be uid or company id
|
||||
CustomData string `json:"custom_data,omitempty"`
|
||||
}
|
||||
|
||||
type AttachmentType string
|
||||
|
||||
const (
|
||||
AttachmentTypeVacancy AttachmentType = "vacancy"
|
||||
AttachmentTypeCV AttachmentType = "cv"
|
||||
AttachmentTypeProfile AttachmentType = "profile"
|
||||
AttachmentTypeCompany AttachmentType = "company"
|
||||
AttachmentTypeBankAccount AttachmentType = "bank_account"
|
||||
AttachmentTypeSubmission AttachmentType = "submission"
|
||||
)
|
||||
325
internal/feed/service.go
Normal file
@@ -0,0 +1,325 @@
|
||||
package feed
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
db *sql.DB
|
||||
schemaName string
|
||||
logger *slog.Logger
|
||||
dbClient database.Client //nolint:unused // TODO: переписать на этого клиента в рамках https://tracker.yandex.ru/MOLVARAZRABOTKA-363
|
||||
}
|
||||
|
||||
func NewService(dbUrl, schemaName string, logger *slog.Logger, dbClient database.Client) (*Service, error) {
|
||||
db, err := sql.Open("postgres", dbUrl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening database connection: %w", err)
|
||||
}
|
||||
|
||||
if err := db.Ping(); err != nil {
|
||||
return nil, fmt.Errorf("error pinging database: %w", err)
|
||||
}
|
||||
|
||||
return &Service{
|
||||
db: db,
|
||||
schemaName: schemaName,
|
||||
logger: logger,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetUserEvents(ctx context.Context, filter Filter, userType string) ([]Event, error) {
|
||||
companyIDs, err := s.GetCompanyIdsByUid(ctx, filter.OwnerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
psql := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
|
||||
|
||||
baseQuery := psql.Select(
|
||||
"id", "owner_id", "owner_type", "message", "event_type", "visibility", "company_id",
|
||||
"payload", "is_cancelled", "cancellation_reason", "created_at", "updated_at",
|
||||
).From(fmt.Sprintf("%s.%s", pq.QuoteIdentifier(s.schemaName), constants.FeedEventsTableName))
|
||||
|
||||
conditions := []sq.Sqlizer{
|
||||
sq.Eq{"owner_id": filter.OwnerID},
|
||||
sq.And{
|
||||
sq.Eq{"visibility": VisibilityCompanyWide},
|
||||
sq.Expr("company_id = ANY(?)", pq.Array(companyIDs)),
|
||||
},
|
||||
sq.And{
|
||||
sq.Expr("payload->>'additional_receiver' IS NOT NULL"),
|
||||
sq.Or{
|
||||
sq.Expr("(payload->>'additional_receiver')::uuid = ?::uuid", filter.OwnerID),
|
||||
sq.Expr("(payload->>'additional_receiver')::text = ANY(?)", pq.Array(companyIDs)),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if userType == RoleAgent.String() {
|
||||
conditions = append(conditions, sq.Eq{"visibility": VisibilityPublic})
|
||||
}
|
||||
|
||||
query := baseQuery.Where(sq.Or(conditions))
|
||||
|
||||
if len(filter.EventTypes) > 0 {
|
||||
query = query.Where(sq.Expr("event_type = ANY(?)", pq.Array(filter.EventTypes)))
|
||||
}
|
||||
|
||||
if !filter.ShowCancelled {
|
||||
query = query.Where(sq.Eq{"is_cancelled": false})
|
||||
}
|
||||
|
||||
query = query.OrderBy("created_at DESC").
|
||||
Limit(filter.Limit).
|
||||
Offset(filter.Offset)
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build query: %w", err)
|
||||
}
|
||||
|
||||
s.logger.Debug("Executing GetUserEvents query", "query", sqlQuery, "args", args)
|
||||
|
||||
rows, err := s.db.QueryContext(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query events: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var events []Event
|
||||
|
||||
for rows.Next() {
|
||||
event, err := s.scanEventRow(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
events = append(events, event)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error iterating event rows: %w", err)
|
||||
}
|
||||
|
||||
s.logger.Debug("GetUserEvents completed successfully",
|
||||
slog.Int("count", len(events)),
|
||||
slog.String("owner_id", filter.OwnerID),
|
||||
slog.String("user_type", userType),
|
||||
slog.String("company_ids", fmt.Sprintf("%v", companyIDs)),
|
||||
slog.Any("filter", filter),
|
||||
)
|
||||
|
||||
return events, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetCompanyIdsByUid(ctx context.Context, ownerID string) ([]string, error) {
|
||||
psql := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
|
||||
query := psql.Select("company_id").
|
||||
From(fmt.Sprintf("%s.%s", pq.QuoteIdentifier(s.schemaName), constants.ClientTableName)).
|
||||
Where(sq.Eq{"uid": ownerID})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build query: %w", err)
|
||||
}
|
||||
|
||||
var companyID sql.NullString
|
||||
|
||||
if err = s.db.QueryRowContext(ctx, sqlQuery, args...).Scan(&companyID); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("failed to get company Id: %w", err)
|
||||
}
|
||||
|
||||
if companyID.Valid {
|
||||
return []string{companyID.String}, nil
|
||||
}
|
||||
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
func (s *Service) scanEventRow(rows *sql.Rows) (Event, error) {
|
||||
var (
|
||||
event Event
|
||||
payload []byte
|
||||
companyIDScan sql.NullString
|
||||
cancellationReasonScan sql.NullString
|
||||
)
|
||||
|
||||
if err := rows.Scan(
|
||||
&event.Id,
|
||||
&event.OwnerId,
|
||||
&event.OwnerType,
|
||||
&event.Message,
|
||||
&event.EventType,
|
||||
&event.Visibility,
|
||||
&companyIDScan,
|
||||
&payload,
|
||||
&event.IsCancelled,
|
||||
&cancellationReasonScan,
|
||||
&event.CreatedAt,
|
||||
&event.UpdatedAt,
|
||||
); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return Event{}, nil
|
||||
}
|
||||
|
||||
return Event{}, fmt.Errorf("failed to scan event: %w", err)
|
||||
}
|
||||
|
||||
event.processNullableFields(companyIDScan, cancellationReasonScan)
|
||||
event.processPayload(payload)
|
||||
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (e *Event) processPayload(payload []byte) {
|
||||
if len(payload) == 0 {
|
||||
e.Payload = EventPayload{}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(payload, &e.Payload); err != nil {
|
||||
e.Payload = EventPayload{}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) AddUserEvent(ctx context.Context, event *Event) error {
|
||||
if event == nil {
|
||||
return ErrCreationInvalidData
|
||||
}
|
||||
|
||||
if event.Id == "" {
|
||||
event.Id = "MSG_" + uuid.New().String()
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
event.CreatedAt = now
|
||||
event.UpdatedAt = now
|
||||
|
||||
payloadBytes, err := json.Marshal(event.Payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal payload: %w", err)
|
||||
}
|
||||
|
||||
var payloadArg interface{} = payloadBytes
|
||||
if string(payloadBytes) == "null" || string(payloadBytes) == "{}" {
|
||||
payloadArg = nil
|
||||
}
|
||||
|
||||
psql := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
|
||||
query := psql.Insert(fmt.Sprintf("%s.%s", pq.QuoteIdentifier(s.schemaName), constants.FeedEventsTableName)).
|
||||
Columns(
|
||||
"id", "owner_id", "owner_type", "message", "event_type", "visibility", "company_id",
|
||||
"payload", "is_cancelled", "cancellation_reason", "created_at", "updated_at",
|
||||
).
|
||||
Values(
|
||||
event.Id,
|
||||
event.OwnerId,
|
||||
event.OwnerType,
|
||||
event.Message,
|
||||
event.EventType,
|
||||
event.Visibility,
|
||||
event.CompanyID,
|
||||
payloadArg,
|
||||
event.IsCancelled,
|
||||
event.CancellationReason,
|
||||
event.CreatedAt,
|
||||
event.UpdatedAt,
|
||||
)
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build query: %w", err)
|
||||
}
|
||||
|
||||
_, err = s.db.ExecContext(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to insert event: %w", err)
|
||||
}
|
||||
|
||||
s.logger.Debug("Event added successfully", "event_id", event.Id)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) CancelEvents(ctx context.Context, attachmentID, cancellationReason string) error {
|
||||
psql := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
|
||||
query := psql.Update(fmt.Sprintf("%s.%s", pq.QuoteIdentifier(s.schemaName), constants.FeedEventsTableName)).
|
||||
Set("is_cancelled", true).
|
||||
Set("cancellation_reason", cancellationReason).
|
||||
Set("updated_at", sq.Expr("NOW()")).
|
||||
Where(sq.Expr("payload ->> 'attachment_id' = ?", attachmentID)).
|
||||
Where(sq.Eq{"is_cancelled": false})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build query: %w", err)
|
||||
}
|
||||
|
||||
result, err := s.db.ExecContext(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute cancel events query for attachmentID %s: %w", attachmentID, err)
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get affected rows for attachmentID %s: %w", attachmentID, err)
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
s.logger.Debug("No active events found or updated for cancellation", "attachment_id", attachmentID)
|
||||
} else {
|
||||
s.logger.Debug("Events cancelled successfully", "attachment_id", attachmentID, "count", rowsAffected)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) GetAgentIdBySubmissionId(ctx context.Context, submissionId string) (string, error) {
|
||||
psql := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
|
||||
query := psql.Select("uid").
|
||||
From(fmt.Sprintf("%s.%s", pq.QuoteIdentifier(s.schemaName), constants.SubmissionTableName)).
|
||||
Where(sq.Eq{"id": submissionId})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to build query: %w", err)
|
||||
}
|
||||
|
||||
var agentId string
|
||||
|
||||
if err = s.db.QueryRowContext(ctx, sqlQuery, args...).Scan(&agentId); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return "", ErrNotFound
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("failed to get agent Id: %w", err)
|
||||
}
|
||||
|
||||
if agentId == "" {
|
||||
s.logger.Debug("Agent Id not found", "submission_id", submissionId)
|
||||
|
||||
return "", ErrNotFound
|
||||
}
|
||||
|
||||
return agentId, nil
|
||||
}
|
||||
15
internal/file_manager/errors.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package filemanager
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrInvalidFileType = errors.New("invalid file type")
|
||||
ErrParameterNotFound = errors.New("parameter required, but not found")
|
||||
ErrFileNotFound = errors.New("file not found")
|
||||
|
||||
ErrFileAlreadyExists = errors.New("file already exists")
|
||||
ErrFailedUploadFile = errors.New("failed to upload file to S3")
|
||||
ErrFailedToCacheUrl = errors.New("failed to cache URL")
|
||||
ErrMsgReadFile = errors.New("failed to read file")
|
||||
ErrMsgGetPresignedURL = errors.New("failed to get presigned URL")
|
||||
)
|
||||
127
internal/file_manager/local_storage/storage.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
filemanager "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/file_manager"
|
||||
)
|
||||
|
||||
type Storage struct {
|
||||
basePath string
|
||||
}
|
||||
|
||||
func New(basePath string) *Storage {
|
||||
return &Storage{
|
||||
basePath: basePath,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Storage) GetFilePaths(
|
||||
ctx context.Context,
|
||||
fileType filemanager.FileType,
|
||||
parameters filemanager.ParameterTable,
|
||||
) ([]string, error) {
|
||||
var dirPath string
|
||||
|
||||
fileNames := make([]string, 0)
|
||||
|
||||
switch fileType {
|
||||
case filemanager.AvatarFileType:
|
||||
userId, ok := parameters[filemanager.UserIdParam]
|
||||
if !ok {
|
||||
return nil, filemanager.ErrParameterNotFound
|
||||
}
|
||||
|
||||
dirPath = filepath.Join(s.basePath, userId.(string), "avatars")
|
||||
|
||||
case filemanager.CVFileType:
|
||||
submId, ok := parameters[filemanager.SubmissionIdParam]
|
||||
if !ok {
|
||||
return nil, filemanager.ErrParameterNotFound
|
||||
}
|
||||
|
||||
dirPath = filepath.Join(s.basePath, "CVs", submId.(string))
|
||||
|
||||
default:
|
||||
return nil, filemanager.ErrInvalidFileType
|
||||
}
|
||||
|
||||
if _, err := os.Stat(dirPath); os.IsNotExist(err) {
|
||||
return nil, filemanager.ErrFileNotFound
|
||||
}
|
||||
|
||||
if err := filepath.WalkDir(dirPath, func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
fileNames = append(fileNames, path)
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(fileNames) == 0 {
|
||||
return nil, filemanager.ErrFileNotFound
|
||||
}
|
||||
|
||||
return fileNames, nil
|
||||
}
|
||||
|
||||
func (s *Storage) SaveFile(
|
||||
ctx context.Context,
|
||||
fileType filemanager.FileType,
|
||||
file multipart.File,
|
||||
fileHeader *multipart.FileHeader,
|
||||
parameters filemanager.ParameterTable,
|
||||
) error {
|
||||
var dirPath string
|
||||
|
||||
switch fileType {
|
||||
case filemanager.AvatarFileType:
|
||||
userId, ok := parameters[filemanager.UserIdParam]
|
||||
if !ok {
|
||||
return filemanager.ErrParameterNotFound
|
||||
}
|
||||
|
||||
dirPath = filepath.Join(s.basePath, userId.(string), "avatars")
|
||||
|
||||
case filemanager.CVFileType:
|
||||
submId, ok := parameters[filemanager.SubmissionIdParam]
|
||||
if !ok {
|
||||
return filemanager.ErrParameterNotFound
|
||||
}
|
||||
|
||||
dirPath = filepath.Join(s.basePath, "CVs", submId.(string))
|
||||
|
||||
default:
|
||||
return filemanager.ErrInvalidFileType
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(dirPath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filePath := filepath.Join(dirPath, fileHeader.Filename)
|
||||
|
||||
dstFile, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dstFile.Close()
|
||||
|
||||
if _, err := io.Copy(dstFile, file); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
39
internal/file_manager/manager.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package filemanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"mime/multipart"
|
||||
)
|
||||
|
||||
type FileType string
|
||||
|
||||
const (
|
||||
AvatarFileType FileType = "avatar"
|
||||
CVFileType FileType = "cv"
|
||||
)
|
||||
|
||||
type ParameterType string
|
||||
|
||||
const (
|
||||
UserIdParam ParameterType = "user_id"
|
||||
VacancyIdParam ParameterType = "vacancy_id"
|
||||
SubmissionIdParam ParameterType = "submission_id"
|
||||
)
|
||||
|
||||
type ParameterTable map[ParameterType]any
|
||||
|
||||
type UserFileManager interface {
|
||||
GetFilePaths(
|
||||
ctx context.Context,
|
||||
fileType FileType,
|
||||
parameters ParameterTable,
|
||||
) ([]string, error)
|
||||
|
||||
SaveFile(
|
||||
ctx context.Context,
|
||||
fileType FileType,
|
||||
file multipart.File,
|
||||
fileHeader *multipart.FileHeader,
|
||||
parameters ParameterTable,
|
||||
) error
|
||||
}
|
||||
156
internal/file_manager/s3_storage/storage.go
Normal file
@@ -0,0 +1,156 @@
|
||||
package s3_storage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/cache"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
|
||||
filemanager "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/file_manager"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/object_storage"
|
||||
"github.com/aws/smithy-go/ptr"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type S3Storage struct {
|
||||
objectStorage object_storage.Client
|
||||
cacheClient cache.Client
|
||||
}
|
||||
|
||||
func NewS3Storage(objectStorage object_storage.Client, cacheClient cache.Client) *S3Storage {
|
||||
return &S3Storage{
|
||||
objectStorage: objectStorage,
|
||||
cacheClient: cacheClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S3Storage) GetFilePaths(
|
||||
ctx context.Context,
|
||||
fileType filemanager.FileType,
|
||||
parameters filemanager.ParameterTable,
|
||||
) ([]string, error) {
|
||||
objectKey, category, err := s.buildObjectKey(fileType, parameters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Сначала пытаемся получить URL из кэша
|
||||
cachedURL, err := s.getCachedURL(ctx, objectKey, category)
|
||||
if err == nil && cachedURL != "" {
|
||||
return []string{cachedURL}, nil
|
||||
}
|
||||
|
||||
// Получаем линк из s3
|
||||
url, err := s.objectStorage.GetPresignedLink(ctx, objectKey, category,
|
||||
object_storage.LinkOptions{
|
||||
TTL: ptr.Duration(constants.DefaultFileTTL),
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, object_storage.ErrObjectNotFound) {
|
||||
return nil, filemanager.ErrFileNotFound
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%s: %w", filemanager.ErrMsgGetPresignedURL, err)
|
||||
}
|
||||
|
||||
// Кэшируем URL
|
||||
if err := s.cacheURL(ctx, objectKey, category, url); err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", filemanager.ErrFailedToCacheUrl, err)
|
||||
}
|
||||
|
||||
return []string{url}, nil
|
||||
}
|
||||
|
||||
func (s *S3Storage) SaveFile(
|
||||
ctx context.Context,
|
||||
fileType filemanager.FileType,
|
||||
file multipart.File,
|
||||
fileHeader *multipart.FileHeader,
|
||||
parameters filemanager.ParameterTable,
|
||||
) error {
|
||||
objectKey, category, err := s.buildObjectKey(fileType, parameters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if _, err := buf.ReadFrom(file); err != nil {
|
||||
return fmt.Errorf("%s: %w", filemanager.ErrMsgReadFile, err)
|
||||
}
|
||||
|
||||
// Определяем тип контента
|
||||
contentType := s.getContentType(fileHeader.Filename)
|
||||
|
||||
// Загружаем файл в S3
|
||||
err = s.objectStorage.PutNewObject(ctx, objectKey, category,
|
||||
bytes.NewReader(buf.Bytes()),
|
||||
object_storage.PutOptions{
|
||||
ContentType: contentType,
|
||||
})
|
||||
if err != nil {
|
||||
// Обрабатываем случай существующего файла
|
||||
if errors.Is(err, object_storage.ErrObjectAlreadyExists) {
|
||||
return filemanager.ErrFileAlreadyExists
|
||||
}
|
||||
|
||||
return fmt.Errorf("%s: %w", filemanager.ErrFailedUploadFile, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Создаем ключ объекта S3 на основе типа файла и параметров
|
||||
func (s *S3Storage) buildObjectKey(fileType filemanager.FileType, parameters filemanager.ParameterTable) (string, object_storage.Category, error) {
|
||||
switch fileType {
|
||||
case filemanager.AvatarFileType:
|
||||
userID, ok := parameters[filemanager.UserIdParam]
|
||||
if !ok {
|
||||
return "", "", filemanager.ErrParameterNotFound
|
||||
}
|
||||
|
||||
return fmt.Sprintf(objectKeyAvatarTemplate, userID), object_storage.LogoCategory, nil
|
||||
|
||||
case filemanager.CVFileType:
|
||||
submissionID, ok := parameters[filemanager.SubmissionIdParam]
|
||||
if !ok {
|
||||
return "", "", filemanager.ErrParameterNotFound
|
||||
}
|
||||
|
||||
return fmt.Sprintf(objectKeyCVTemplate, submissionID), object_storage.DocumentCategory, nil
|
||||
|
||||
default:
|
||||
return "", "", filemanager.ErrInvalidFileType
|
||||
}
|
||||
}
|
||||
|
||||
// getContentType определяет тип контента по расширению
|
||||
func (s *S3Storage) getContentType(filename string) string {
|
||||
ext := strings.ToLower(filepath.Ext(filename))
|
||||
|
||||
if ct, ok := ContentTypes[ext]; ok {
|
||||
return ct
|
||||
}
|
||||
|
||||
if ct := mime.TypeByExtension(ext); ct != "" {
|
||||
return ct
|
||||
}
|
||||
|
||||
return defaultContentType
|
||||
}
|
||||
|
||||
func (s *S3Storage) getCachedURL(ctx context.Context, objectKey string, category object_storage.Category) (string, error) {
|
||||
cacheKey := fmt.Sprintf(cacheKeyTemplate, category, objectKey)
|
||||
return s.cacheClient.Get(ctx, cacheKey, cache.DocumentsValueType)
|
||||
}
|
||||
|
||||
func (s *S3Storage) cacheURL(ctx context.Context, objectKey string, category object_storage.Category, url string) error {
|
||||
cacheKey := fmt.Sprintf(cacheKeyTemplate, category, objectKey)
|
||||
cacheDuration := constants.DefaultFileTTL - time.Hour
|
||||
|
||||
return s.cacheClient.Set(ctx, cacheKey, cache.DocumentsValueType, url, cacheDuration)
|
||||
}
|
||||
22
internal/file_manager/s3_storage/types.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package s3_storage
|
||||
|
||||
var ContentTypes = map[string]string{
|
||||
".pdf": "application/pdf",
|
||||
".txt": "text/plain",
|
||||
".doc": "application/msword",
|
||||
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
".rtf": "application/rtf",
|
||||
".odt": "application/vnd.oasis.opendocument.text",
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".webp": "image/webp",
|
||||
}
|
||||
|
||||
// Константы для ключей
|
||||
const (
|
||||
objectKeyAvatarTemplate = "%s_avatar"
|
||||
objectKeyCVTemplate = "%s_cv"
|
||||
cacheKeyTemplate = "%s_%s"
|
||||
defaultContentType = "application/octet-stream"
|
||||
)
|
||||
65
internal/form_generator/generator.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package formgenerator
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"errors"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//go:embed templates/index.html
|
||||
var formTemplate string
|
||||
|
||||
//go:embed templates
|
||||
var formFS embed.FS
|
||||
|
||||
var (
|
||||
requiredFields []string = []string{
|
||||
"VacancyName",
|
||||
"Address",
|
||||
"WorkFormat",
|
||||
"SalaryTop",
|
||||
"SalaryBottom",
|
||||
"Requirements",
|
||||
"Responsibilities",
|
||||
"Description",
|
||||
|
||||
"VacancyId",
|
||||
"AgentId",
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = errors.New("One of the required fields is not set")
|
||||
)
|
||||
|
||||
func GetFileSystem() (fs.FS, error) {
|
||||
formFs, err := fs.Sub(formFS, "templates")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return formFs, nil
|
||||
}
|
||||
|
||||
func GenerateForm(formData map[string]string) (string, error) {
|
||||
for _, field := range requiredFields {
|
||||
if _, ok := formData[field]; !ok {
|
||||
return "", ErrNotFound
|
||||
}
|
||||
}
|
||||
|
||||
tmpl, err := template.New("index.html").Parse(formTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf strings.Builder
|
||||
|
||||
if err = tmpl.Execute(&buf, formData); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
"DQUHFmFzc2V0cy9pbWFnZXMvbG9nby5zdmcMAQ0BBwVhc3NldAcWYXNzZXRzL2ltYWdlcy9sb2dvLnN2ZwcdYXNzZXRzL2ltYWdlcy9yZXN1bWUtZmlsZS5zdmcMAQ0BBwVhc3NldAcdYXNzZXRzL2ltYWdlcy9yZXN1bWUtZmlsZS5zdmcHHWFzc2V0cy9pbWFnZXMvcmVzdW1lLWxpbmsuc3ZnDAENAQcFYXNzZXQHHWFzc2V0cy9pbWFnZXMvcmVzdW1lLWxpbmsuc3ZnBxZhc3NldHMvaW1hZ2VzL3NlbmQuc3ZnDAENAQcFYXNzZXQHFmFzc2V0cy9pbWFnZXMvc2VuZC5zdmcHMnBhY2thZ2VzL2N1cGVydGlub19pY29ucy9hc3NldHMvQ3VwZXJ0aW5vSWNvbnMudHRmDAENAQcFYXNzZXQHMnBhY2thZ2VzL2N1cGVydGlub19pY29ucy9hc3NldHMvQ3VwZXJ0aW5vSWNvbnMudHRm"
|
||||
@@ -0,0 +1 @@
|
||||
{"assets/images/logo.svg":["assets/images/logo.svg"],"assets/images/resume-file.svg":["assets/images/resume-file.svg"],"assets/images/resume-link.svg":["assets/images/resume-link.svg"],"assets/images/send.svg":["assets/images/send.svg"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"]}
|
||||
@@ -0,0 +1 @@
|
||||
[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"packages/cupertino_icons/CupertinoIcons","fonts":[{"asset":"packages/cupertino_icons/assets/CupertinoIcons.ttf"}]}]
|
||||
@@ -0,0 +1,8 @@
|
||||
<svg width="138" height="28" viewBox="0 0 138 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.1226 15.512L6.39303 0.519165H0V26.4807H7.23678V16.0636L13.2404 26.4807H16.7776L22.8462 15.7067L22.9111 26.4807H30.1154V0.519165H23.6575L15.1226 15.512Z" fill="#1454B2"/>
|
||||
<path d="M55.0384 1.7524C52.8641 0.584135 50.3978 0 47.6718 0C44.9459 0 42.4795 0.584135 40.3053 1.7524C38.131 2.92067 36.3786 4.54327 35.1454 6.58774C33.9122 8.63221 33.2632 10.9688 33.2632 13.5325C33.2632 16.0962 33.8798 18.4327 35.1454 20.4772C36.3786 22.5216 38.131 24.1442 40.3053 25.3125C42.4795 26.4808 44.9459 27.0649 47.6718 27.0649C50.3978 27.0649 52.8641 26.4808 55.0384 25.3125C57.2127 24.1442 58.9651 22.5216 60.1983 20.4772C61.4315 18.4327 62.0805 16.0962 62.0805 13.5325C62.0805 10.9688 61.4639 8.63221 60.1983 6.58774C58.9651 4.51082 57.2127 2.88822 55.0384 1.7524ZM50.9819 19.5685C50.0084 20.1526 48.8726 20.4447 47.6718 20.4447C46.4387 20.4447 45.3353 20.1526 44.3293 19.5685C43.3557 18.9844 42.5444 18.1731 41.9927 17.1346C41.4086 16.0962 41.1165 14.863 41.1165 13.5C41.1165 12.137 41.4086 10.9038 41.9927 9.86539C42.5769 8.82692 43.3557 8.01562 44.3293 7.43149C45.3028 6.84736 46.4387 6.55529 47.6718 6.55529C48.905 6.55529 50.0084 6.84736 50.9819 7.43149C51.9555 8.01562 52.7668 8.82692 53.3185 9.86539C53.9026 10.9038 54.1947 12.137 54.1947 13.5C54.1947 14.863 53.9026 16.0962 53.3185 17.1346C52.7668 18.1731 51.9879 19.0168 50.9819 19.5685Z" fill="#1454B2"/>
|
||||
<path d="M73.0167 0.519165H65.2283V26.4807H85.1213V20.185H73.0167V0.519165Z" fill="#1454B2"/>
|
||||
<path d="M90.833 0.519165H82.428L93.5265 26.4807H100.99L101.347 25.6694L90.833 0.519165Z" fill="#1454B2"/>
|
||||
<path d="M104.073 19.2439L112.121 0.519165H104.365L100.276 10.0925L104.073 19.2439Z" fill="#3B9BF2"/>
|
||||
<path d="M126.465 0.519165H119.423L125.492 15.6418H119.877H112.316L107.546 26.4807H115.529L117.541 21.548H127.861L129.84 26.4807H137.986L126.465 0.519165Z" fill="#1454B2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 365 KiB |
|
After Width: | Height: | Size: 41 KiB |
192
internal/form_generator/templates/canvaskit/canvaskit.js
Normal file
@@ -0,0 +1,192 @@
|
||||
|
||||
var CanvasKitInit = (() => {
|
||||
var _scriptName = import.meta.url;
|
||||
|
||||
return (
|
||||
function(moduleArg = {}) {
|
||||
var moduleRtn;
|
||||
|
||||
var r=moduleArg,aa,ca,da=new Promise((a,b)=>{aa=a;ca=b}),ea="object"==typeof window,ha="function"==typeof importScripts;
|
||||
(function(a){a.ce=a.ce||[];a.ce.push(function(){a.MakeSWCanvasSurface=function(b){var c=b,e="undefined"!==typeof OffscreenCanvas&&c instanceof OffscreenCanvas;if(!("undefined"!==typeof HTMLCanvasElement&&c instanceof HTMLCanvasElement||e||(c=document.getElementById(b),c)))throw"Canvas with id "+b+" was not found";if(b=a.MakeSurface(c.width,c.height))b.Ae=c;return b};a.MakeCanvasSurface||(a.MakeCanvasSurface=a.MakeSWCanvasSurface);a.MakeSurface=function(b,c){var e={width:b,height:c,colorType:a.ColorType.RGBA_8888,
|
||||
alphaType:a.AlphaType.Unpremul,colorSpace:a.ColorSpace.SRGB},f=b*c*4,k=a._malloc(f);if(e=a.Surface._makeRasterDirect(e,k,4*b))e.Ae=null,e.$e=b,e.Xe=c,e.Ye=f,e.He=k,e.getCanvas().clear(a.TRANSPARENT);return e};a.MakeRasterDirectSurface=function(b,c,e){return a.Surface._makeRasterDirect(b,c.byteOffset,e)};a.Surface.prototype.flush=function(b){a.$d(this.Zd);this._flush();if(this.Ae){var c=new Uint8ClampedArray(a.HEAPU8.buffer,this.He,this.Ye);c=new ImageData(c,this.$e,this.Xe);b?this.Ae.getContext("2d").putImageData(c,
|
||||
0,0,b[0],b[1],b[2]-b[0],b[3]-b[1]):this.Ae.getContext("2d").putImageData(c,0,0)}};a.Surface.prototype.dispose=function(){this.He&&a._free(this.He);this.delete()};a.$d=a.$d||function(){};a.Be=a.Be||function(){return null}})})(r);
|
||||
(function(a){a.ce=a.ce||[];a.ce.push(function(){function b(l,p,v){return l&&l.hasOwnProperty(p)?l[p]:v}function c(l){var p=ja(ka);ka[p]=l;return p}function e(l){return l.naturalHeight||l.videoHeight||l.displayHeight||l.height}function f(l){return l.naturalWidth||l.videoWidth||l.displayWidth||l.width}function k(l,p,v,w){l.bindTexture(l.TEXTURE_2D,p);w||v.alphaType!==a.AlphaType.Premul||l.pixelStorei(l.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0);return p}function n(l,p,v){v||p.alphaType!==a.AlphaType.Premul||
|
||||
l.pixelStorei(l.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);l.bindTexture(l.TEXTURE_2D,null)}a.GetWebGLContext=function(l,p){if(!l)throw"null canvas passed into makeWebGLContext";var v={alpha:b(p,"alpha",1),depth:b(p,"depth",1),stencil:b(p,"stencil",8),antialias:b(p,"antialias",0),premultipliedAlpha:b(p,"premultipliedAlpha",1),preserveDrawingBuffer:b(p,"preserveDrawingBuffer",0),preferLowPowerToHighPerformance:b(p,"preferLowPowerToHighPerformance",0),failIfMajorPerformanceCaveat:b(p,"failIfMajorPerformanceCaveat",
|
||||
0),enableExtensionsByDefault:b(p,"enableExtensionsByDefault",1),explicitSwapControl:b(p,"explicitSwapControl",0),renderViaOffscreenBackBuffer:b(p,"renderViaOffscreenBackBuffer",0)};v.majorVersion=p&&p.majorVersion?p.majorVersion:"undefined"!==typeof WebGL2RenderingContext?2:1;if(v.explicitSwapControl)throw"explicitSwapControl is not supported";l=la(l,v);if(!l)return 0;oa(l);z.le.getExtension("WEBGL_debug_renderer_info");return l};a.deleteContext=function(l){z===pa[l]&&(z=null);"object"==typeof JSEvents&&
|
||||
JSEvents.Af(pa[l].le.canvas);pa[l]&&pa[l].le.canvas&&(pa[l].le.canvas.Ve=void 0);pa[l]=null};a._setTextureCleanup({deleteTexture:function(l,p){var v=ka[p];v&&pa[l].le.deleteTexture(v);ka[p]=null}});a.MakeWebGLContext=function(l){if(!this.$d(l))return null;var p=this._MakeGrContext();if(!p)return null;p.Zd=l;var v=p.delete.bind(p);p["delete"]=function(){a.$d(this.Zd);v()}.bind(p);return z.Je=p};a.MakeGrContext=a.MakeWebGLContext;a.GrDirectContext.prototype.getResourceCacheLimitBytes=function(){a.$d(this.Zd);
|
||||
this._getResourceCacheLimitBytes()};a.GrDirectContext.prototype.getResourceCacheUsageBytes=function(){a.$d(this.Zd);this._getResourceCacheUsageBytes()};a.GrDirectContext.prototype.releaseResourcesAndAbandonContext=function(){a.$d(this.Zd);this._releaseResourcesAndAbandonContext()};a.GrDirectContext.prototype.setResourceCacheLimitBytes=function(l){a.$d(this.Zd);this._setResourceCacheLimitBytes(l)};a.MakeOnScreenGLSurface=function(l,p,v,w,A,D){if(!this.$d(l.Zd))return null;p=void 0===A||void 0===D?
|
||||
this._MakeOnScreenGLSurface(l,p,v,w):this._MakeOnScreenGLSurface(l,p,v,w,A,D);if(!p)return null;p.Zd=l.Zd;return p};a.MakeRenderTarget=function(){var l=arguments[0];if(!this.$d(l.Zd))return null;if(3===arguments.length){var p=this._MakeRenderTargetWH(l,arguments[1],arguments[2]);if(!p)return null}else if(2===arguments.length){if(p=this._MakeRenderTargetII(l,arguments[1]),!p)return null}else return null;p.Zd=l.Zd;return p};a.MakeWebGLCanvasSurface=function(l,p,v){p=p||null;var w=l,A="undefined"!==
|
||||
typeof OffscreenCanvas&&w instanceof OffscreenCanvas;if(!("undefined"!==typeof HTMLCanvasElement&&w instanceof HTMLCanvasElement||A||(w=document.getElementById(l),w)))throw"Canvas with id "+l+" was not found";l=this.GetWebGLContext(w,v);if(!l||0>l)throw"failed to create webgl context: err "+l;l=this.MakeWebGLContext(l);p=this.MakeOnScreenGLSurface(l,w.width,w.height,p);return p?p:(p=w.cloneNode(!0),w.parentNode.replaceChild(p,w),p.classList.add("ck-replaced"),a.MakeSWCanvasSurface(p))};a.MakeCanvasSurface=
|
||||
a.MakeWebGLCanvasSurface;a.Surface.prototype.makeImageFromTexture=function(l,p){a.$d(this.Zd);l=c(l);if(p=this._makeImageFromTexture(this.Zd,l,p))p.ue=l;return p};a.Surface.prototype.makeImageFromTextureSource=function(l,p,v){p||={height:e(l),width:f(l),colorType:a.ColorType.RGBA_8888,alphaType:v?a.AlphaType.Premul:a.AlphaType.Unpremul};p.colorSpace||(p.colorSpace=a.ColorSpace.SRGB);a.$d(this.Zd);var w=z.le;v=k(w,w.createTexture(),p,v);2===z.version?w.texImage2D(w.TEXTURE_2D,0,w.RGBA,p.width,p.height,
|
||||
0,w.RGBA,w.UNSIGNED_BYTE,l):w.texImage2D(w.TEXTURE_2D,0,w.RGBA,w.RGBA,w.UNSIGNED_BYTE,l);n(w,p);this._resetContext();return this.makeImageFromTexture(v,p)};a.Surface.prototype.updateTextureFromSource=function(l,p,v){if(l.ue){a.$d(this.Zd);var w=l.getImageInfo(),A=z.le,D=k(A,ka[l.ue],w,v);2===z.version?A.texImage2D(A.TEXTURE_2D,0,A.RGBA,f(p),e(p),0,A.RGBA,A.UNSIGNED_BYTE,p):A.texImage2D(A.TEXTURE_2D,0,A.RGBA,A.RGBA,A.UNSIGNED_BYTE,p);n(A,w,v);this._resetContext();ka[l.ue]=null;l.ue=c(D);w.colorSpace=
|
||||
l.getColorSpace();p=this._makeImageFromTexture(this.Zd,l.ue,w);v=l.Yd.ae;A=l.Yd.ee;l.Yd.ae=p.Yd.ae;l.Yd.ee=p.Yd.ee;p.Yd.ae=v;p.Yd.ee=A;p.delete();w.colorSpace.delete()}};a.MakeLazyImageFromTextureSource=function(l,p,v){p||={height:e(l),width:f(l),colorType:a.ColorType.RGBA_8888,alphaType:v?a.AlphaType.Premul:a.AlphaType.Unpremul};p.colorSpace||(p.colorSpace=a.ColorSpace.SRGB);var w={makeTexture:function(){var A=z,D=A.le,I=k(D,D.createTexture(),p,v);2===A.version?D.texImage2D(D.TEXTURE_2D,0,D.RGBA,
|
||||
p.width,p.height,0,D.RGBA,D.UNSIGNED_BYTE,l):D.texImage2D(D.TEXTURE_2D,0,D.RGBA,D.RGBA,D.UNSIGNED_BYTE,l);n(D,p,v);return c(I)},freeSrc:function(){}};"VideoFrame"===l.constructor.name&&(w.freeSrc=function(){l.close()});return a.Image._makeFromGenerator(p,w)};a.$d=function(l){return l?oa(l):!1};a.Be=function(){return z&&z.Je&&!z.Je.isDeleted()?z.Je:null}})})(r);
|
||||
(function(a){function b(g){return(f(255*g[3])<<24|f(255*g[0])<<16|f(255*g[1])<<8|f(255*g[2])<<0)>>>0}function c(g){if(g&&g._ck)return g;if(g instanceof Float32Array){for(var d=Math.floor(g.length/4),h=new Uint32Array(d),m=0;m<d;m++)h[m]=b(g.slice(4*m,4*(m+1)));return h}if(g instanceof Uint32Array)return g;if(g instanceof Array&&g[0]instanceof Float32Array)return g.map(b)}function e(g){if(void 0===g)return 1;var d=parseFloat(g);return g&&-1!==g.indexOf("%")?d/100:d}function f(g){return Math.round(Math.max(0,
|
||||
Math.min(g||0,255)))}function k(g,d){d&&d._ck||a._free(g)}function n(g,d,h){if(!g||!g.length)return K;if(g&&g._ck)return g.byteOffset;var m=a[d].BYTES_PER_ELEMENT;h||=a._malloc(g.length*m);a[d].set(g,h/m);return h}function l(g){var d={he:K,count:g.length,colorType:a.ColorType.RGBA_F32};if(g instanceof Float32Array)d.he=n(g,"HEAPF32"),d.count=g.length/4;else if(g instanceof Uint32Array)d.he=n(g,"HEAPU32"),d.colorType=a.ColorType.RGBA_8888;else if(g instanceof Array){if(g&&g.length){for(var h=a._malloc(16*
|
||||
g.length),m=0,t=h/4,u=0;u<g.length;u++)for(var x=0;4>x;x++)a.HEAPF32[t+m]=g[u][x],m++;g=h}else g=K;d.he=g}else throw"Invalid argument to copyFlexibleColorArray, Not a color array "+typeof g;return d}function p(g){if(!g)return K;var d=ba.toTypedArray();if(g.length){if(6===g.length||9===g.length)return n(g,"HEAPF32",P),6===g.length&&a.HEAPF32.set(Wc,6+P/4),P;if(16===g.length)return d[0]=g[0],d[1]=g[1],d[2]=g[3],d[3]=g[4],d[4]=g[5],d[5]=g[7],d[6]=g[12],d[7]=g[13],d[8]=g[15],P;throw"invalid matrix size";
|
||||
}if(void 0===g.m11)throw"invalid matrix argument";d[0]=g.m11;d[1]=g.m21;d[2]=g.m41;d[3]=g.m12;d[4]=g.m22;d[5]=g.m42;d[6]=g.m14;d[7]=g.m24;d[8]=g.m44;return P}function v(g){if(!g)return K;var d=Y.toTypedArray();if(g.length){if(16!==g.length&&6!==g.length&&9!==g.length)throw"invalid matrix size";if(16===g.length)return n(g,"HEAPF32",ma);d.fill(0);d[0]=g[0];d[1]=g[1];d[3]=g[2];d[4]=g[3];d[5]=g[4];d[7]=g[5];d[10]=1;d[12]=g[6];d[13]=g[7];d[15]=g[8];6===g.length&&(d[12]=0,d[13]=0,d[15]=1);return ma}if(void 0===
|
||||
g.m11)throw"invalid matrix argument";d[0]=g.m11;d[1]=g.m21;d[2]=g.m31;d[3]=g.m41;d[4]=g.m12;d[5]=g.m22;d[6]=g.m32;d[7]=g.m42;d[8]=g.m13;d[9]=g.m23;d[10]=g.m33;d[11]=g.m43;d[12]=g.m14;d[13]=g.m24;d[14]=g.m34;d[15]=g.m44;return ma}function w(g,d){return n(g,"HEAPF32",d||ia)}function A(g,d,h,m){var t=Ea.toTypedArray();t[0]=g;t[1]=d;t[2]=h;t[3]=m;return ia}function D(g){for(var d=new Float32Array(4),h=0;4>h;h++)d[h]=a.HEAPF32[g/4+h];return d}function I(g,d){return n(g,"HEAPF32",d||W)}function R(g,d){return n(g,
|
||||
"HEAPF32",d||ub)}a.Color=function(g,d,h,m){void 0===m&&(m=1);return a.Color4f(f(g)/255,f(d)/255,f(h)/255,m)};a.ColorAsInt=function(g,d,h,m){void 0===m&&(m=255);return(f(m)<<24|f(g)<<16|f(d)<<8|f(h)<<0&268435455)>>>0};a.Color4f=function(g,d,h,m){void 0===m&&(m=1);return Float32Array.of(g,d,h,m)};Object.defineProperty(a,"TRANSPARENT",{get:function(){return a.Color4f(0,0,0,0)}});Object.defineProperty(a,"BLACK",{get:function(){return a.Color4f(0,0,0,1)}});Object.defineProperty(a,"WHITE",{get:function(){return a.Color4f(1,
|
||||
1,1,1)}});Object.defineProperty(a,"RED",{get:function(){return a.Color4f(1,0,0,1)}});Object.defineProperty(a,"GREEN",{get:function(){return a.Color4f(0,1,0,1)}});Object.defineProperty(a,"BLUE",{get:function(){return a.Color4f(0,0,1,1)}});Object.defineProperty(a,"YELLOW",{get:function(){return a.Color4f(1,1,0,1)}});Object.defineProperty(a,"CYAN",{get:function(){return a.Color4f(0,1,1,1)}});Object.defineProperty(a,"MAGENTA",{get:function(){return a.Color4f(1,0,1,1)}});a.getColorComponents=function(g){return[Math.floor(255*
|
||||
g[0]),Math.floor(255*g[1]),Math.floor(255*g[2]),g[3]]};a.parseColorString=function(g,d){g=g.toLowerCase();if(g.startsWith("#")){d=255;switch(g.length){case 9:d=parseInt(g.slice(7,9),16);case 7:var h=parseInt(g.slice(1,3),16);var m=parseInt(g.slice(3,5),16);var t=parseInt(g.slice(5,7),16);break;case 5:d=17*parseInt(g.slice(4,5),16);case 4:h=17*parseInt(g.slice(1,2),16),m=17*parseInt(g.slice(2,3),16),t=17*parseInt(g.slice(3,4),16)}return a.Color(h,m,t,d/255)}return g.startsWith("rgba")?(g=g.slice(5,
|
||||
-1),g=g.split(","),a.Color(+g[0],+g[1],+g[2],e(g[3]))):g.startsWith("rgb")?(g=g.slice(4,-1),g=g.split(","),a.Color(+g[0],+g[1],+g[2],e(g[3]))):g.startsWith("gray(")||g.startsWith("hsl")||!d||(g=d[g],void 0===g)?a.BLACK:g};a.multiplyByAlpha=function(g,d){g=g.slice();g[3]=Math.max(0,Math.min(g[3]*d,1));return g};a.Malloc=function(g,d){var h=a._malloc(d*g.BYTES_PER_ELEMENT);return{_ck:!0,length:d,byteOffset:h,qe:null,subarray:function(m,t){m=this.toTypedArray().subarray(m,t);m._ck=!0;return m},toTypedArray:function(){if(this.qe&&
|
||||
this.qe.length)return this.qe;this.qe=new g(a.HEAPU8.buffer,h,d);this.qe._ck=!0;return this.qe}}};a.Free=function(g){a._free(g.byteOffset);g.byteOffset=K;g.toTypedArray=null;g.qe=null};var P=K,ba,ma=K,Y,ia=K,Ea,fa,W=K,Ub,Ba=K,Vb,vb=K,Wb,wb=K,$a,Na=K,Xb,ub=K,Yb,Zb=K,Wc=Float32Array.of(0,0,1),K=0;a.onRuntimeInitialized=function(){function g(d,h,m,t,u,x,C){x||(x=4*t.width,t.colorType===a.ColorType.RGBA_F16?x*=2:t.colorType===a.ColorType.RGBA_F32&&(x*=4));var G=x*t.height;var F=u?u.byteOffset:a._malloc(G);
|
||||
if(C?!d._readPixels(t,F,x,h,m,C):!d._readPixels(t,F,x,h,m))return u||a._free(F),null;if(u)return u.toTypedArray();switch(t.colorType){case a.ColorType.RGBA_8888:case a.ColorType.RGBA_F16:d=(new Uint8Array(a.HEAPU8.buffer,F,G)).slice();break;case a.ColorType.RGBA_F32:d=(new Float32Array(a.HEAPU8.buffer,F,G)).slice();break;default:return null}a._free(F);return d}Ea=a.Malloc(Float32Array,4);ia=Ea.byteOffset;Y=a.Malloc(Float32Array,16);ma=Y.byteOffset;ba=a.Malloc(Float32Array,9);P=ba.byteOffset;Xb=a.Malloc(Float32Array,
|
||||
12);ub=Xb.byteOffset;Yb=a.Malloc(Float32Array,12);Zb=Yb.byteOffset;fa=a.Malloc(Float32Array,4);W=fa.byteOffset;Ub=a.Malloc(Float32Array,4);Ba=Ub.byteOffset;Vb=a.Malloc(Float32Array,3);vb=Vb.byteOffset;Wb=a.Malloc(Float32Array,3);wb=Wb.byteOffset;$a=a.Malloc(Int32Array,4);Na=$a.byteOffset;a.ColorSpace.SRGB=a.ColorSpace._MakeSRGB();a.ColorSpace.DISPLAY_P3=a.ColorSpace._MakeDisplayP3();a.ColorSpace.ADOBE_RGB=a.ColorSpace._MakeAdobeRGB();a.GlyphRunFlags={IsWhiteSpace:a._GlyphRunFlags_isWhiteSpace};a.Path.MakeFromCmds=
|
||||
function(d){var h=n(d,"HEAPF32"),m=a.Path._MakeFromCmds(h,d.length);k(h,d);return m};a.Path.MakeFromVerbsPointsWeights=function(d,h,m){var t=n(d,"HEAPU8"),u=n(h,"HEAPF32"),x=n(m,"HEAPF32"),C=a.Path._MakeFromVerbsPointsWeights(t,d.length,u,h.length,x,m&&m.length||0);k(t,d);k(u,h);k(x,m);return C};a.Path.prototype.addArc=function(d,h,m){d=I(d);this._addArc(d,h,m);return this};a.Path.prototype.addCircle=function(d,h,m,t){this._addCircle(d,h,m,!!t);return this};a.Path.prototype.addOval=function(d,h,m){void 0===
|
||||
m&&(m=1);d=I(d);this._addOval(d,!!h,m);return this};a.Path.prototype.addPath=function(){var d=Array.prototype.slice.call(arguments),h=d[0],m=!1;"boolean"===typeof d[d.length-1]&&(m=d.pop());if(1===d.length)this._addPath(h,1,0,0,0,1,0,0,0,1,m);else if(2===d.length)d=d[1],this._addPath(h,d[0],d[1],d[2],d[3],d[4],d[5],d[6]||0,d[7]||0,d[8]||1,m);else if(7===d.length||10===d.length)this._addPath(h,d[1],d[2],d[3],d[4],d[5],d[6],d[7]||0,d[8]||0,d[9]||1,m);else return null;return this};a.Path.prototype.addPoly=
|
||||
function(d,h){var m=n(d,"HEAPF32");this._addPoly(m,d.length/2,h);k(m,d);return this};a.Path.prototype.addRect=function(d,h){d=I(d);this._addRect(d,!!h);return this};a.Path.prototype.addRRect=function(d,h){d=R(d);this._addRRect(d,!!h);return this};a.Path.prototype.addVerbsPointsWeights=function(d,h,m){var t=n(d,"HEAPU8"),u=n(h,"HEAPF32"),x=n(m,"HEAPF32");this._addVerbsPointsWeights(t,d.length,u,h.length,x,m&&m.length||0);k(t,d);k(u,h);k(x,m)};a.Path.prototype.arc=function(d,h,m,t,u,x){d=a.LTRBRect(d-
|
||||
m,h-m,d+m,h+m);u=(u-t)/Math.PI*180-360*!!x;x=new a.Path;x.addArc(d,t/Math.PI*180,u);this.addPath(x,!0);x.delete();return this};a.Path.prototype.arcToOval=function(d,h,m,t){d=I(d);this._arcToOval(d,h,m,t);return this};a.Path.prototype.arcToRotated=function(d,h,m,t,u,x,C){this._arcToRotated(d,h,m,!!t,!!u,x,C);return this};a.Path.prototype.arcToTangent=function(d,h,m,t,u){this._arcToTangent(d,h,m,t,u);return this};a.Path.prototype.close=function(){this._close();return this};a.Path.prototype.conicTo=
|
||||
function(d,h,m,t,u){this._conicTo(d,h,m,t,u);return this};a.Path.prototype.computeTightBounds=function(d){this._computeTightBounds(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.Path.prototype.cubicTo=function(d,h,m,t,u,x){this._cubicTo(d,h,m,t,u,x);return this};a.Path.prototype.dash=function(d,h,m){return this._dash(d,h,m)?this:null};a.Path.prototype.getBounds=function(d){this._getBounds(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.Path.prototype.lineTo=function(d,
|
||||
h){this._lineTo(d,h);return this};a.Path.prototype.moveTo=function(d,h){this._moveTo(d,h);return this};a.Path.prototype.offset=function(d,h){this._transform(1,0,d,0,1,h,0,0,1);return this};a.Path.prototype.quadTo=function(d,h,m,t){this._quadTo(d,h,m,t);return this};a.Path.prototype.rArcTo=function(d,h,m,t,u,x,C){this._rArcTo(d,h,m,t,u,x,C);return this};a.Path.prototype.rConicTo=function(d,h,m,t,u){this._rConicTo(d,h,m,t,u);return this};a.Path.prototype.rCubicTo=function(d,h,m,t,u,x){this._rCubicTo(d,
|
||||
h,m,t,u,x);return this};a.Path.prototype.rLineTo=function(d,h){this._rLineTo(d,h);return this};a.Path.prototype.rMoveTo=function(d,h){this._rMoveTo(d,h);return this};a.Path.prototype.rQuadTo=function(d,h,m,t){this._rQuadTo(d,h,m,t);return this};a.Path.prototype.stroke=function(d){d=d||{};d.width=d.width||1;d.miter_limit=d.miter_limit||4;d.cap=d.cap||a.StrokeCap.Butt;d.join=d.join||a.StrokeJoin.Miter;d.precision=d.precision||1;return this._stroke(d)?this:null};a.Path.prototype.transform=function(){if(1===
|
||||
arguments.length){var d=arguments[0];this._transform(d[0],d[1],d[2],d[3],d[4],d[5],d[6]||0,d[7]||0,d[8]||1)}else if(6===arguments.length||9===arguments.length)d=arguments,this._transform(d[0],d[1],d[2],d[3],d[4],d[5],d[6]||0,d[7]||0,d[8]||1);else throw"transform expected to take 1 or 9 arguments. Got "+arguments.length;return this};a.Path.prototype.trim=function(d,h,m){return this._trim(d,h,!!m)?this:null};a.Image.prototype.encodeToBytes=function(d,h){var m=a.Be();d=d||a.ImageFormat.PNG;h=h||100;
|
||||
return m?this._encodeToBytes(d,h,m):this._encodeToBytes(d,h)};a.Image.prototype.makeShaderCubic=function(d,h,m,t,u){u=p(u);return this._makeShaderCubic(d,h,m,t,u)};a.Image.prototype.makeShaderOptions=function(d,h,m,t,u){u=p(u);return this._makeShaderOptions(d,h,m,t,u)};a.Image.prototype.readPixels=function(d,h,m,t,u){var x=a.Be();return g(this,d,h,m,t,u,x)};a.Canvas.prototype.clear=function(d){a.$d(this.Zd);d=w(d);this._clear(d)};a.Canvas.prototype.clipRRect=function(d,h,m){a.$d(this.Zd);d=R(d);this._clipRRect(d,
|
||||
h,m)};a.Canvas.prototype.clipRect=function(d,h,m){a.$d(this.Zd);d=I(d);this._clipRect(d,h,m)};a.Canvas.prototype.concat=function(d){a.$d(this.Zd);d=v(d);this._concat(d)};a.Canvas.prototype.drawArc=function(d,h,m,t,u){a.$d(this.Zd);d=I(d);this._drawArc(d,h,m,t,u)};a.Canvas.prototype.drawAtlas=function(d,h,m,t,u,x,C){if(d&&t&&h&&m&&h.length===m.length){a.$d(this.Zd);u||(u=a.BlendMode.SrcOver);var G=n(h,"HEAPF32"),F=n(m,"HEAPF32"),T=m.length/4,U=n(c(x),"HEAPU32");if(C&&"B"in C&&"C"in C)this._drawAtlasCubic(d,
|
||||
F,G,U,T,u,C.B,C.C,t);else{let q=a.FilterMode.Linear,y=a.MipmapMode.None;C&&(q=C.filter,"mipmap"in C&&(y=C.mipmap));this._drawAtlasOptions(d,F,G,U,T,u,q,y,t)}k(G,h);k(F,m);k(U,x)}};a.Canvas.prototype.drawCircle=function(d,h,m,t){a.$d(this.Zd);this._drawCircle(d,h,m,t)};a.Canvas.prototype.drawColor=function(d,h){a.$d(this.Zd);d=w(d);void 0!==h?this._drawColor(d,h):this._drawColor(d)};a.Canvas.prototype.drawColorInt=function(d,h){a.$d(this.Zd);this._drawColorInt(d,h||a.BlendMode.SrcOver)};a.Canvas.prototype.drawColorComponents=
|
||||
function(d,h,m,t,u){a.$d(this.Zd);d=A(d,h,m,t);void 0!==u?this._drawColor(d,u):this._drawColor(d)};a.Canvas.prototype.drawDRRect=function(d,h,m){a.$d(this.Zd);d=R(d,ub);h=R(h,Zb);this._drawDRRect(d,h,m)};a.Canvas.prototype.drawImage=function(d,h,m,t){a.$d(this.Zd);this._drawImage(d,h,m,t||null)};a.Canvas.prototype.drawImageCubic=function(d,h,m,t,u,x){a.$d(this.Zd);this._drawImageCubic(d,h,m,t,u,x||null)};a.Canvas.prototype.drawImageOptions=function(d,h,m,t,u,x){a.$d(this.Zd);this._drawImageOptions(d,
|
||||
h,m,t,u,x||null)};a.Canvas.prototype.drawImageNine=function(d,h,m,t,u){a.$d(this.Zd);h=n(h,"HEAP32",Na);m=I(m);this._drawImageNine(d,h,m,t,u||null)};a.Canvas.prototype.drawImageRect=function(d,h,m,t,u){a.$d(this.Zd);I(h,W);I(m,Ba);this._drawImageRect(d,W,Ba,t,!!u)};a.Canvas.prototype.drawImageRectCubic=function(d,h,m,t,u,x){a.$d(this.Zd);I(h,W);I(m,Ba);this._drawImageRectCubic(d,W,Ba,t,u,x||null)};a.Canvas.prototype.drawImageRectOptions=function(d,h,m,t,u,x){a.$d(this.Zd);I(h,W);I(m,Ba);this._drawImageRectOptions(d,
|
||||
W,Ba,t,u,x||null)};a.Canvas.prototype.drawLine=function(d,h,m,t,u){a.$d(this.Zd);this._drawLine(d,h,m,t,u)};a.Canvas.prototype.drawOval=function(d,h){a.$d(this.Zd);d=I(d);this._drawOval(d,h)};a.Canvas.prototype.drawPaint=function(d){a.$d(this.Zd);this._drawPaint(d)};a.Canvas.prototype.drawParagraph=function(d,h,m){a.$d(this.Zd);this._drawParagraph(d,h,m)};a.Canvas.prototype.drawPatch=function(d,h,m,t,u){if(24>d.length)throw"Need 12 cubic points";if(h&&4>h.length)throw"Need 4 colors";if(m&&8>m.length)throw"Need 4 shader coordinates";
|
||||
a.$d(this.Zd);const x=n(d,"HEAPF32"),C=h?n(c(h),"HEAPU32"):K,G=m?n(m,"HEAPF32"):K;t||(t=a.BlendMode.Modulate);this._drawPatch(x,C,G,t,u);k(G,m);k(C,h);k(x,d)};a.Canvas.prototype.drawPath=function(d,h){a.$d(this.Zd);this._drawPath(d,h)};a.Canvas.prototype.drawPicture=function(d){a.$d(this.Zd);this._drawPicture(d)};a.Canvas.prototype.drawPoints=function(d,h,m){a.$d(this.Zd);var t=n(h,"HEAPF32");this._drawPoints(d,t,h.length/2,m);k(t,h)};a.Canvas.prototype.drawRRect=function(d,h){a.$d(this.Zd);d=R(d);
|
||||
this._drawRRect(d,h)};a.Canvas.prototype.drawRect=function(d,h){a.$d(this.Zd);d=I(d);this._drawRect(d,h)};a.Canvas.prototype.drawRect4f=function(d,h,m,t,u){a.$d(this.Zd);this._drawRect4f(d,h,m,t,u)};a.Canvas.prototype.drawShadow=function(d,h,m,t,u,x,C){a.$d(this.Zd);var G=n(u,"HEAPF32"),F=n(x,"HEAPF32");h=n(h,"HEAPF32",vb);m=n(m,"HEAPF32",wb);this._drawShadow(d,h,m,t,G,F,C);k(G,u);k(F,x)};a.getShadowLocalBounds=function(d,h,m,t,u,x,C){d=p(d);m=n(m,"HEAPF32",vb);t=n(t,"HEAPF32",wb);if(!this._getShadowLocalBounds(d,
|
||||
h,m,t,u,x,W))return null;h=fa.toTypedArray();return C?(C.set(h),C):h.slice()};a.Canvas.prototype.drawTextBlob=function(d,h,m,t){a.$d(this.Zd);this._drawTextBlob(d,h,m,t)};a.Canvas.prototype.drawVertices=function(d,h,m){a.$d(this.Zd);this._drawVertices(d,h,m)};a.Canvas.prototype.getDeviceClipBounds=function(d){this._getDeviceClipBounds(Na);var h=$a.toTypedArray();d?d.set(h):d=h.slice();return d};a.Canvas.prototype.quickReject=function(d){d=I(d);return this._quickReject(d)};a.Canvas.prototype.getLocalToDevice=
|
||||
function(){this._getLocalToDevice(ma);for(var d=ma,h=Array(16),m=0;16>m;m++)h[m]=a.HEAPF32[d/4+m];return h};a.Canvas.prototype.getTotalMatrix=function(){this._getTotalMatrix(P);for(var d=Array(9),h=0;9>h;h++)d[h]=a.HEAPF32[P/4+h];return d};a.Canvas.prototype.makeSurface=function(d){d=this._makeSurface(d);d.Zd=this.Zd;return d};a.Canvas.prototype.readPixels=function(d,h,m,t,u){a.$d(this.Zd);return g(this,d,h,m,t,u)};a.Canvas.prototype.saveLayer=function(d,h,m,t,u){h=I(h);return this._saveLayer(d||
|
||||
null,h,m||null,t||0,u||a.TileMode.Clamp)};a.Canvas.prototype.writePixels=function(d,h,m,t,u,x,C,G){if(d.byteLength%(h*m))throw"pixels length must be a multiple of the srcWidth * srcHeight";a.$d(this.Zd);var F=d.byteLength/(h*m);x=x||a.AlphaType.Unpremul;C=C||a.ColorType.RGBA_8888;G=G||a.ColorSpace.SRGB;var T=F*h;F=n(d,"HEAPU8");h=this._writePixels({width:h,height:m,colorType:C,alphaType:x,colorSpace:G},F,T,t,u);k(F,d);return h};a.ColorFilter.MakeBlend=function(d,h,m){d=w(d);m=m||a.ColorSpace.SRGB;
|
||||
return a.ColorFilter._MakeBlend(d,h,m)};a.ColorFilter.MakeMatrix=function(d){if(!d||20!==d.length)throw"invalid color matrix";var h=n(d,"HEAPF32"),m=a.ColorFilter._makeMatrix(h);k(h,d);return m};a.ContourMeasure.prototype.getPosTan=function(d,h){this._getPosTan(d,W);d=fa.toTypedArray();return h?(h.set(d),h):d.slice()};a.ImageFilter.prototype.getOutputBounds=function(d,h,m){d=I(d,W);h=p(h);this._getOutputBounds(d,h,Na);h=$a.toTypedArray();return m?(m.set(h),m):h.slice()};a.ImageFilter.MakeDropShadow=
|
||||
function(d,h,m,t,u,x){u=w(u,ia);return a.ImageFilter._MakeDropShadow(d,h,m,t,u,x)};a.ImageFilter.MakeDropShadowOnly=function(d,h,m,t,u,x){u=w(u,ia);return a.ImageFilter._MakeDropShadowOnly(d,h,m,t,u,x)};a.ImageFilter.MakeImage=function(d,h,m,t){m=I(m,W);t=I(t,Ba);if("B"in h&&"C"in h)return a.ImageFilter._MakeImageCubic(d,h.B,h.C,m,t);const u=h.filter;let x=a.MipmapMode.None;"mipmap"in h&&(x=h.mipmap);return a.ImageFilter._MakeImageOptions(d,u,x,m,t)};a.ImageFilter.MakeMatrixTransform=function(d,h,
|
||||
m){d=p(d);if("B"in h&&"C"in h)return a.ImageFilter._MakeMatrixTransformCubic(d,h.B,h.C,m);const t=h.filter;let u=a.MipmapMode.None;"mipmap"in h&&(u=h.mipmap);return a.ImageFilter._MakeMatrixTransformOptions(d,t,u,m)};a.Paint.prototype.getColor=function(){this._getColor(ia);return D(ia)};a.Paint.prototype.setColor=function(d,h){h=h||null;d=w(d);this._setColor(d,h)};a.Paint.prototype.setColorComponents=function(d,h,m,t,u){u=u||null;d=A(d,h,m,t);this._setColor(d,u)};a.Path.prototype.getPoint=function(d,
|
||||
h){this._getPoint(d,W);d=fa.toTypedArray();return h?(h[0]=d[0],h[1]=d[1],h):d.slice(0,2)};a.Picture.prototype.makeShader=function(d,h,m,t,u){t=p(t);u=I(u);return this._makeShader(d,h,m,t,u)};a.Picture.prototype.cullRect=function(d){this._cullRect(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.PictureRecorder.prototype.beginRecording=function(d,h){d=I(d);return this._beginRecording(d,!!h)};a.Surface.prototype.getCanvas=function(){var d=this._getCanvas();d.Zd=this.Zd;return d};a.Surface.prototype.makeImageSnapshot=
|
||||
function(d){a.$d(this.Zd);d=n(d,"HEAP32",Na);return this._makeImageSnapshot(d)};a.Surface.prototype.makeSurface=function(d){a.$d(this.Zd);d=this._makeSurface(d);d.Zd=this.Zd;return d};a.Surface.prototype.Ze=function(d,h){this.te||(this.te=this.getCanvas());return requestAnimationFrame(function(){a.$d(this.Zd);d(this.te);this.flush(h)}.bind(this))};a.Surface.prototype.requestAnimationFrame||(a.Surface.prototype.requestAnimationFrame=a.Surface.prototype.Ze);a.Surface.prototype.We=function(d,h){this.te||
|
||||
(this.te=this.getCanvas());requestAnimationFrame(function(){a.$d(this.Zd);d(this.te);this.flush(h);this.dispose()}.bind(this))};a.Surface.prototype.drawOnce||(a.Surface.prototype.drawOnce=a.Surface.prototype.We);a.PathEffect.MakeDash=function(d,h){h||=0;if(!d.length||1===d.length%2)throw"Intervals array must have even length";var m=n(d,"HEAPF32");h=a.PathEffect._MakeDash(m,d.length,h);k(m,d);return h};a.PathEffect.MakeLine2D=function(d,h){h=p(h);return a.PathEffect._MakeLine2D(d,h)};a.PathEffect.MakePath2D=
|
||||
function(d,h){d=p(d);return a.PathEffect._MakePath2D(d,h)};a.Shader.MakeColor=function(d,h){h=h||null;d=w(d);return a.Shader._MakeColor(d,h)};a.Shader.Blend=a.Shader.MakeBlend;a.Shader.Color=a.Shader.MakeColor;a.Shader.MakeLinearGradient=function(d,h,m,t,u,x,C,G){G=G||null;var F=l(m),T=n(t,"HEAPF32");C=C||0;x=p(x);var U=fa.toTypedArray();U.set(d);U.set(h,2);d=a.Shader._MakeLinearGradient(W,F.he,F.colorType,T,F.count,u,C,x,G);k(F.he,m);t&&k(T,t);return d};a.Shader.MakeRadialGradient=function(d,h,m,
|
||||
t,u,x,C,G){G=G||null;var F=l(m),T=n(t,"HEAPF32");C=C||0;x=p(x);d=a.Shader._MakeRadialGradient(d[0],d[1],h,F.he,F.colorType,T,F.count,u,C,x,G);k(F.he,m);t&&k(T,t);return d};a.Shader.MakeSweepGradient=function(d,h,m,t,u,x,C,G,F,T){T=T||null;var U=l(m),q=n(t,"HEAPF32");C=C||0;G=G||0;F=F||360;x=p(x);d=a.Shader._MakeSweepGradient(d,h,U.he,U.colorType,q,U.count,u,G,F,C,x,T);k(U.he,m);t&&k(q,t);return d};a.Shader.MakeTwoPointConicalGradient=function(d,h,m,t,u,x,C,G,F,T){T=T||null;var U=l(u),q=n(x,"HEAPF32");
|
||||
F=F||0;G=p(G);var y=fa.toTypedArray();y.set(d);y.set(m,2);d=a.Shader._MakeTwoPointConicalGradient(W,h,t,U.he,U.colorType,q,U.count,C,F,G,T);k(U.he,u);x&&k(q,x);return d};a.Vertices.prototype.bounds=function(d){this._bounds(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.ce&&a.ce.forEach(function(d){d()})};a.computeTonalColors=function(g){var d=n(g.ambient,"HEAPF32"),h=n(g.spot,"HEAPF32");this._computeTonalColors(d,h);var m={ambient:D(d),spot:D(h)};k(d,g.ambient);k(h,g.spot);return m};
|
||||
a.LTRBRect=function(g,d,h,m){return Float32Array.of(g,d,h,m)};a.XYWHRect=function(g,d,h,m){return Float32Array.of(g,d,g+h,d+m)};a.LTRBiRect=function(g,d,h,m){return Int32Array.of(g,d,h,m)};a.XYWHiRect=function(g,d,h,m){return Int32Array.of(g,d,g+h,d+m)};a.RRectXY=function(g,d,h){return Float32Array.of(g[0],g[1],g[2],g[3],d,h,d,h,d,h,d,h)};a.MakeAnimatedImageFromEncoded=function(g){g=new Uint8Array(g);var d=a._malloc(g.byteLength);a.HEAPU8.set(g,d);return(g=a._decodeAnimatedImage(d,g.byteLength))?
|
||||
g:null};a.MakeImageFromEncoded=function(g){g=new Uint8Array(g);var d=a._malloc(g.byteLength);a.HEAPU8.set(g,d);return(g=a._decodeImage(d,g.byteLength))?g:null};var ab=null;a.MakeImageFromCanvasImageSource=function(g){var d=g.width,h=g.height;ab||=document.createElement("canvas");ab.width=d;ab.height=h;var m=ab.getContext("2d",{willReadFrequently:!0});m.drawImage(g,0,0);g=m.getImageData(0,0,d,h);return a.MakeImage({width:d,height:h,alphaType:a.AlphaType.Unpremul,colorType:a.ColorType.RGBA_8888,colorSpace:a.ColorSpace.SRGB},
|
||||
g.data,4*d)};a.MakeImage=function(g,d,h){var m=a._malloc(d.length);a.HEAPU8.set(d,m);return a._MakeImage(g,m,d.length,h)};a.MakeVertices=function(g,d,h,m,t,u){var x=t&&t.length||0,C=0;h&&h.length&&(C|=1);m&&m.length&&(C|=2);void 0===u||u||(C|=4);g=new a._VerticesBuilder(g,d.length/2,x,C);n(d,"HEAPF32",g.positions());g.texCoords()&&n(h,"HEAPF32",g.texCoords());g.colors()&&n(c(m),"HEAPU32",g.colors());g.indices()&&n(t,"HEAPU16",g.indices());return g.detach()};(function(g){g.ce=g.ce||[];g.ce.push(function(){function d(q){q&&
|
||||
(q.dir=0===q.dir?g.TextDirection.RTL:g.TextDirection.LTR);return q}function h(q){if(!q||!q.length)return[];for(var y=[],N=0;N<q.length;N+=5){var X=g.LTRBRect(q[N],q[N+1],q[N+2],q[N+3]),xa=g.TextDirection.LTR;0===q[N+4]&&(xa=g.TextDirection.RTL);y.push({rect:X,dir:xa})}g._free(q.byteOffset);return y}function m(q){q=q||{};void 0===q.weight&&(q.weight=g.FontWeight.Normal);q.width=q.width||g.FontWidth.Normal;q.slant=q.slant||g.FontSlant.Upright;return q}function t(q){if(!q||!q.length)return K;for(var y=
|
||||
[],N=0;N<q.length;N++){var X=u(q[N]);y.push(X)}return n(y,"HEAPU32")}function u(q){if(G[q])return G[q];var y=qa(q)+1,N=g._malloc(y);ra(q,N,y);return G[q]=N}function x(q){q._colorPtr=w(q.color);q._foregroundColorPtr=K;q._backgroundColorPtr=K;q._decorationColorPtr=K;q.foregroundColor&&(q._foregroundColorPtr=w(q.foregroundColor,F));q.backgroundColor&&(q._backgroundColorPtr=w(q.backgroundColor,T));q.decorationColor&&(q._decorationColorPtr=w(q.decorationColor,U));Array.isArray(q.fontFamilies)&&q.fontFamilies.length?
|
||||
(q._fontFamiliesPtr=t(q.fontFamilies),q._fontFamiliesLen=q.fontFamilies.length):(q._fontFamiliesPtr=K,q._fontFamiliesLen=0);if(q.locale){var y=q.locale;q._localePtr=u(y);q._localeLen=qa(y)}else q._localePtr=K,q._localeLen=0;if(Array.isArray(q.shadows)&&q.shadows.length){y=q.shadows;var N=y.map(function(na){return na.color||g.BLACK}),X=y.map(function(na){return na.blurRadius||0});q._shadowLen=y.length;for(var xa=g._malloc(8*y.length),xb=xa/4,yb=0;yb<y.length;yb++){var $b=y[yb].offset||[0,0];g.HEAPF32[xb]=
|
||||
$b[0];g.HEAPF32[xb+1]=$b[1];xb+=2}q._shadowColorsPtr=l(N).he;q._shadowOffsetsPtr=xa;q._shadowBlurRadiiPtr=n(X,"HEAPF32")}else q._shadowLen=0,q._shadowColorsPtr=K,q._shadowOffsetsPtr=K,q._shadowBlurRadiiPtr=K;Array.isArray(q.fontFeatures)&&q.fontFeatures.length?(y=q.fontFeatures,N=y.map(function(na){return na.name}),X=y.map(function(na){return na.value}),q._fontFeatureLen=y.length,q._fontFeatureNamesPtr=t(N),q._fontFeatureValuesPtr=n(X,"HEAPU32")):(q._fontFeatureLen=0,q._fontFeatureNamesPtr=K,q._fontFeatureValuesPtr=
|
||||
K);Array.isArray(q.fontVariations)&&q.fontVariations.length?(y=q.fontVariations,N=y.map(function(na){return na.axis}),X=y.map(function(na){return na.value}),q._fontVariationLen=y.length,q._fontVariationAxesPtr=t(N),q._fontVariationValuesPtr=n(X,"HEAPF32")):(q._fontVariationLen=0,q._fontVariationAxesPtr=K,q._fontVariationValuesPtr=K)}function C(q){g._free(q._fontFamiliesPtr);g._free(q._shadowColorsPtr);g._free(q._shadowOffsetsPtr);g._free(q._shadowBlurRadiiPtr);g._free(q._fontFeatureNamesPtr);g._free(q._fontFeatureValuesPtr);
|
||||
g._free(q._fontVariationAxesPtr);g._free(q._fontVariationValuesPtr)}g.Paragraph.prototype.getRectsForRange=function(q,y,N,X){q=this._getRectsForRange(q,y,N,X);return h(q)};g.Paragraph.prototype.getRectsForPlaceholders=function(){var q=this._getRectsForPlaceholders();return h(q)};g.Paragraph.prototype.getGlyphInfoAt=function(q){return d(this._getGlyphInfoAt(q))};g.Paragraph.prototype.getClosestGlyphInfoAtCoordinate=function(q,y){return d(this._getClosestGlyphInfoAtCoordinate(q,y))};g.TypefaceFontProvider.prototype.registerFont=
|
||||
function(q,y){q=g.Typeface.MakeTypefaceFromData(q);if(!q)return null;y=u(y);this._registerFont(q,y)};g.ParagraphStyle=function(q){q.disableHinting=q.disableHinting||!1;if(q.ellipsis){var y=q.ellipsis;q._ellipsisPtr=u(y);q._ellipsisLen=qa(y)}else q._ellipsisPtr=K,q._ellipsisLen=0;null==q.heightMultiplier&&(q.heightMultiplier=-1);q.maxLines=q.maxLines||0;q.replaceTabCharacters=q.replaceTabCharacters||!1;y=(y=q.strutStyle)||{};y.strutEnabled=y.strutEnabled||!1;y.strutEnabled&&Array.isArray(y.fontFamilies)&&
|
||||
y.fontFamilies.length?(y._fontFamiliesPtr=t(y.fontFamilies),y._fontFamiliesLen=y.fontFamilies.length):(y._fontFamiliesPtr=K,y._fontFamiliesLen=0);y.fontStyle=m(y.fontStyle);null==y.fontSize&&(y.fontSize=-1);null==y.heightMultiplier&&(y.heightMultiplier=-1);y.halfLeading=y.halfLeading||!1;y.leading=y.leading||0;y.forceStrutHeight=y.forceStrutHeight||!1;q.strutStyle=y;q.textAlign=q.textAlign||g.TextAlign.Start;q.textDirection=q.textDirection||g.TextDirection.LTR;q.textHeightBehavior=q.textHeightBehavior||
|
||||
g.TextHeightBehavior.All;q.textStyle=g.TextStyle(q.textStyle);q.applyRoundingHack=!1!==q.applyRoundingHack;return q};g.TextStyle=function(q){q.color||(q.color=g.BLACK);q.decoration=q.decoration||0;q.decorationThickness=q.decorationThickness||0;q.decorationStyle=q.decorationStyle||g.DecorationStyle.Solid;q.textBaseline=q.textBaseline||g.TextBaseline.Alphabetic;null==q.fontSize&&(q.fontSize=-1);q.letterSpacing=q.letterSpacing||0;q.wordSpacing=q.wordSpacing||0;null==q.heightMultiplier&&(q.heightMultiplier=
|
||||
-1);q.halfLeading=q.halfLeading||!1;q.fontStyle=m(q.fontStyle);return q};var G={},F=g._malloc(16),T=g._malloc(16),U=g._malloc(16);g.ParagraphBuilder.Make=function(q,y){x(q.textStyle);y=g.ParagraphBuilder._Make(q,y);C(q.textStyle);return y};g.ParagraphBuilder.MakeFromFontProvider=function(q,y){x(q.textStyle);y=g.ParagraphBuilder._MakeFromFontProvider(q,y);C(q.textStyle);return y};g.ParagraphBuilder.MakeFromFontCollection=function(q,y){x(q.textStyle);y=g.ParagraphBuilder._MakeFromFontCollection(q,y);
|
||||
C(q.textStyle);return y};g.ParagraphBuilder.ShapeText=function(q,y,N){let X=0;for(const xa of y)X+=xa.length;if(X!==q.length)throw"Accumulated block lengths must equal text.length";return g.ParagraphBuilder._ShapeText(q,y,N)};g.ParagraphBuilder.prototype.pushStyle=function(q){x(q);this._pushStyle(q);C(q)};g.ParagraphBuilder.prototype.pushPaintStyle=function(q,y,N){x(q);this._pushPaintStyle(q,y,N);C(q)};g.ParagraphBuilder.prototype.addPlaceholder=function(q,y,N,X,xa){N=N||g.PlaceholderAlignment.Baseline;
|
||||
X=X||g.TextBaseline.Alphabetic;this._addPlaceholder(q||0,y||0,N,X,xa||0)};g.ParagraphBuilder.prototype.setWordsUtf8=function(q){var y=n(q,"HEAPU32");this._setWordsUtf8(y,q&&q.length||0);k(y,q)};g.ParagraphBuilder.prototype.setWordsUtf16=function(q){var y=n(q,"HEAPU32");this._setWordsUtf16(y,q&&q.length||0);k(y,q)};g.ParagraphBuilder.prototype.setGraphemeBreaksUtf8=function(q){var y=n(q,"HEAPU32");this._setGraphemeBreaksUtf8(y,q&&q.length||0);k(y,q)};g.ParagraphBuilder.prototype.setGraphemeBreaksUtf16=
|
||||
function(q){var y=n(q,"HEAPU32");this._setGraphemeBreaksUtf16(y,q&&q.length||0);k(y,q)};g.ParagraphBuilder.prototype.setLineBreaksUtf8=function(q){var y=n(q,"HEAPU32");this._setLineBreaksUtf8(y,q&&q.length||0);k(y,q)};g.ParagraphBuilder.prototype.setLineBreaksUtf16=function(q){var y=n(q,"HEAPU32");this._setLineBreaksUtf16(y,q&&q.length||0);k(y,q)}})})(r);a.ce=a.ce||[];a.ce.push(function(){a.Path.prototype.op=function(g,d){return this._op(g,d)?this:null};a.Path.prototype.simplify=function(){return this._simplify()?
|
||||
this:null}});a.ce=a.ce||[];a.ce.push(function(){a.Canvas.prototype.drawText=function(g,d,h,m,t){var u=qa(g),x=a._malloc(u+1);ra(g,x,u+1);this._drawSimpleText(x,u,d,h,t,m);a._free(x)};a.Canvas.prototype.drawGlyphs=function(g,d,h,m,t,u){if(!(2*g.length<=d.length))throw"Not enough positions for the array of gyphs";a.$d(this.Zd);const x=n(g,"HEAPU16"),C=n(d,"HEAPF32");this._drawGlyphs(g.length,x,C,h,m,t,u);k(C,d);k(x,g)};a.Font.prototype.getGlyphBounds=function(g,d,h){var m=n(g,"HEAPU16"),t=a._malloc(16*
|
||||
g.length);this._getGlyphWidthBounds(m,g.length,K,t,d||null);d=new Float32Array(a.HEAPU8.buffer,t,4*g.length);k(m,g);if(h)return h.set(d),a._free(t),h;g=Float32Array.from(d);a._free(t);return g};a.Font.prototype.getGlyphIDs=function(g,d,h){d||(d=g.length);var m=qa(g)+1,t=a._malloc(m);ra(g,t,m);g=a._malloc(2*d);d=this._getGlyphIDs(t,m-1,d,g);a._free(t);if(0>d)return a._free(g),null;t=new Uint16Array(a.HEAPU8.buffer,g,d);if(h)return h.set(t),a._free(g),h;h=Uint16Array.from(t);a._free(g);return h};a.Font.prototype.getGlyphIntercepts=
|
||||
function(g,d,h,m){var t=n(g,"HEAPU16"),u=n(d,"HEAPF32");return this._getGlyphIntercepts(t,g.length,!(g&&g._ck),u,d.length,!(d&&d._ck),h,m)};a.Font.prototype.getGlyphWidths=function(g,d,h){var m=n(g,"HEAPU16"),t=a._malloc(4*g.length);this._getGlyphWidthBounds(m,g.length,t,K,d||null);d=new Float32Array(a.HEAPU8.buffer,t,g.length);k(m,g);if(h)return h.set(d),a._free(t),h;g=Float32Array.from(d);a._free(t);return g};a.FontMgr.FromData=function(){if(!arguments.length)return null;var g=arguments;1===g.length&&
|
||||
Array.isArray(g[0])&&(g=arguments[0]);if(!g.length)return null;for(var d=[],h=[],m=0;m<g.length;m++){var t=new Uint8Array(g[m]),u=n(t,"HEAPU8");d.push(u);h.push(t.byteLength)}d=n(d,"HEAPU32");h=n(h,"HEAPU32");g=a.FontMgr._fromData(d,h,g.length);a._free(d);a._free(h);return g};a.Typeface.MakeTypefaceFromData=function(g){g=new Uint8Array(g);var d=n(g,"HEAPU8");return(g=a.Typeface._MakeTypefaceFromData(d,g.byteLength))?g:null};a.Typeface.MakeFreeTypeFaceFromData=a.Typeface.MakeTypefaceFromData;a.Typeface.prototype.getGlyphIDs=
|
||||
function(g,d,h){d||(d=g.length);var m=qa(g)+1,t=a._malloc(m);ra(g,t,m);g=a._malloc(2*d);d=this._getGlyphIDs(t,m-1,d,g);a._free(t);if(0>d)return a._free(g),null;t=new Uint16Array(a.HEAPU8.buffer,g,d);if(h)return h.set(t),a._free(g),h;h=Uint16Array.from(t);a._free(g);return h};a.TextBlob.MakeOnPath=function(g,d,h,m){if(g&&g.length&&d&&d.countPoints()){if(1===d.countPoints())return this.MakeFromText(g,h);m||=0;var t=h.getGlyphIDs(g);t=h.getGlyphWidths(t);var u=[];d=new a.ContourMeasureIter(d,!1,1);for(var x=
|
||||
d.next(),C=new Float32Array(4),G=0;G<g.length&&x;G++){var F=t[G];m+=F/2;if(m>x.length()){x.delete();x=d.next();if(!x){g=g.substring(0,G);break}m=F/2}x.getPosTan(m,C);var T=C[2],U=C[3];u.push(T,U,C[0]-F/2*T,C[1]-F/2*U);m+=F/2}g=this.MakeFromRSXform(g,u,h);x&&x.delete();d.delete();return g}};a.TextBlob.MakeFromRSXform=function(g,d,h){var m=qa(g)+1,t=a._malloc(m);ra(g,t,m);g=n(d,"HEAPF32");h=a.TextBlob._MakeFromRSXform(t,m-1,g,h);a._free(t);return h?h:null};a.TextBlob.MakeFromRSXformGlyphs=function(g,
|
||||
d,h){var m=n(g,"HEAPU16");d=n(d,"HEAPF32");h=a.TextBlob._MakeFromRSXformGlyphs(m,2*g.length,d,h);k(m,g);return h?h:null};a.TextBlob.MakeFromGlyphs=function(g,d){var h=n(g,"HEAPU16");d=a.TextBlob._MakeFromGlyphs(h,2*g.length,d);k(h,g);return d?d:null};a.TextBlob.MakeFromText=function(g,d){var h=qa(g)+1,m=a._malloc(h);ra(g,m,h);g=a.TextBlob._MakeFromText(m,h-1,d);a._free(m);return g?g:null};a.MallocGlyphIDs=function(g){return a.Malloc(Uint16Array,g)}});a.ce=a.ce||[];a.ce.push(function(){a.MakePicture=
|
||||
function(g){g=new Uint8Array(g);var d=a._malloc(g.byteLength);a.HEAPU8.set(g,d);return(g=a._MakePicture(d,g.byteLength))?g:null}});a.ce=a.ce||[];a.ce.push(function(){a.RuntimeEffect.Make=function(g,d){return a.RuntimeEffect._Make(g,{onError:d||function(h){console.log("RuntimeEffect error",h)}})};a.RuntimeEffect.MakeForBlender=function(g,d){return a.RuntimeEffect._MakeForBlender(g,{onError:d||function(h){console.log("RuntimeEffect error",h)}})};a.RuntimeEffect.prototype.makeShader=function(g,d){var h=
|
||||
!g._ck,m=n(g,"HEAPF32");d=p(d);return this._makeShader(m,4*g.length,h,d)};a.RuntimeEffect.prototype.makeShaderWithChildren=function(g,d,h){var m=!g._ck,t=n(g,"HEAPF32");h=p(h);for(var u=[],x=0;x<d.length;x++)u.push(d[x].Yd.ae);d=n(u,"HEAPU32");return this._makeShaderWithChildren(t,4*g.length,m,d,u.length,h)};a.RuntimeEffect.prototype.makeBlender=function(g){var d=!g._ck,h=n(g,"HEAPF32");return this._makeBlender(h,4*g.length,d)}})})(r);var sa=Object.assign({},r),ta="",ua,va;
|
||||
if(ea||ha)ha?ta=self.location.href:"undefined"!=typeof document&&document.currentScript&&(ta=document.currentScript.src),_scriptName&&(ta=_scriptName),ta.startsWith("blob:")?ta="":ta=ta.substr(0,ta.replace(/[?#].*/,"").lastIndexOf("/")+1),ha&&(va=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),ua=a=>fetch(a,{credentials:"same-origin"}).then(b=>b.ok?b.arrayBuffer():Promise.reject(Error(b.status+" : "+b.url)));
|
||||
var wa=console.log.bind(console),ya=console.error.bind(console);Object.assign(r,sa);sa=null;var za,Aa=!1,Ca,B,Da,Fa,E,H,J,Ga;function Ha(){var a=za.buffer;r.HEAP8=Ca=new Int8Array(a);r.HEAP16=Da=new Int16Array(a);r.HEAPU8=B=new Uint8Array(a);r.HEAPU16=Fa=new Uint16Array(a);r.HEAP32=E=new Int32Array(a);r.HEAPU32=H=new Uint32Array(a);r.HEAPF32=J=new Float32Array(a);r.HEAPF64=Ga=new Float64Array(a)}var Ia=[],Ja=[],Ka=[],La=0,Ma=null,Oa=null;
|
||||
function Pa(a){a="Aborted("+a+")";ya(a);Aa=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");ca(a);throw a;}var Qa=a=>a.startsWith("data:application/octet-stream;base64,"),Ra;function Sa(a){return ua(a).then(b=>new Uint8Array(b),()=>{if(va)var b=va(a);else throw"both async and sync fetching of the wasm failed";return b})}function Ta(a,b,c){return Sa(a).then(e=>WebAssembly.instantiate(e,b)).then(c,e=>{ya(`failed to asynchronously prepare wasm: ${e}`);Pa(e)})}
|
||||
function Ua(a,b){var c=Ra;return"function"!=typeof WebAssembly.instantiateStreaming||Qa(c)||"function"!=typeof fetch?Ta(c,a,b):fetch(c,{credentials:"same-origin"}).then(e=>WebAssembly.instantiateStreaming(e,a).then(b,function(f){ya(`wasm streaming compile failed: ${f}`);ya("falling back to ArrayBuffer instantiation");return Ta(c,a,b)}))}function Va(a){this.name="ExitStatus";this.message=`Program terminated with exit(${a})`;this.status=a}var Wa=a=>{a.forEach(b=>b(r))};
|
||||
class Xa{constructor(a){this.ae=a-24}}
|
||||
var Ya=0,Za=0,bb="undefined"!=typeof TextDecoder?new TextDecoder:void 0,cb=(a,b=0,c=NaN)=>{var e=b+c;for(c=b;a[c]&&!(c>=e);)++c;if(16<c-b&&a.buffer&&bb)return bb.decode(a.subarray(b,c));for(e="";b<c;){var f=a[b++];if(f&128){var k=a[b++]&63;if(192==(f&224))e+=String.fromCharCode((f&31)<<6|k);else{var n=a[b++]&63;f=224==(f&240)?(f&15)<<12|k<<6|n:(f&7)<<18|k<<12|n<<6|a[b++]&63;65536>f?e+=String.fromCharCode(f):(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else e+=String.fromCharCode(f)}return e},
|
||||
db={},eb=a=>{for(;a.length;){var b=a.pop();a.pop()(b)}};function fb(a){return this.fromWireType(H[a>>2])}
|
||||
var gb={},hb={},ib={},jb,lb=(a,b,c)=>{function e(l){l=c(l);if(l.length!==a.length)throw new jb("Mismatched type converter count");for(var p=0;p<a.length;++p)kb(a[p],l[p])}a.forEach(l=>ib[l]=b);var f=Array(b.length),k=[],n=0;b.forEach((l,p)=>{hb.hasOwnProperty(l)?f[p]=hb[l]:(k.push(l),gb.hasOwnProperty(l)||(gb[l]=[]),gb[l].push(()=>{f[p]=hb[l];++n;n===k.length&&e(f)}))});0===k.length&&e(f)},mb,L=a=>{for(var b="";B[a];)b+=mb[B[a++]];return b},M;
|
||||
function nb(a,b,c={}){var e=b.name;if(!a)throw new M(`type "${e}" must have a positive integer typeid pointer`);if(hb.hasOwnProperty(a)){if(c.lf)return;throw new M(`Cannot register type '${e}' twice`);}hb[a]=b;delete ib[a];gb.hasOwnProperty(a)&&(b=gb[a],delete gb[a],b.forEach(f=>f()))}function kb(a,b,c={}){return nb(a,b,c)}
|
||||
var ob=a=>{throw new M(a.Yd.de.be.name+" instance already deleted");},pb=!1,qb=()=>{},rb=(a,b,c)=>{if(b===c)return a;if(void 0===c.ge)return null;a=rb(a,b,c.ge);return null===a?null:c.cf(a)},sb={},tb={},zb=(a,b)=>{if(void 0===b)throw new M("ptr should not be undefined");for(;a.ge;)b=a.ye(b),a=a.ge;return tb[b]},Bb=(a,b)=>{if(!b.de||!b.ae)throw new jb("makeClassHandle requires ptr and ptrType");if(!!b.ie!==!!b.ee)throw new jb("Both smartPtrType and smartPtr must be specified");b.count={value:1};return Ab(Object.create(a,
|
||||
{Yd:{value:b,writable:!0}}))},Ab=a=>{if("undefined"===typeof FinalizationRegistry)return Ab=b=>b,a;pb=new FinalizationRegistry(b=>{b=b.Yd;--b.count.value;0===b.count.value&&(b.ee?b.ie.ne(b.ee):b.de.be.ne(b.ae))});Ab=b=>{var c=b.Yd;c.ee&&pb.register(b,{Yd:c},b);return b};qb=b=>{pb.unregister(b)};return Ab(a)},Cb=[];function Db(){}
|
||||
var Eb=(a,b)=>Object.defineProperty(b,"name",{value:a}),Fb=(a,b,c)=>{if(void 0===a[b].fe){var e=a[b];a[b]=function(...f){if(!a[b].fe.hasOwnProperty(f.length))throw new M(`Function '${c}' called with an invalid number of arguments (${f.length}) - expects one of (${a[b].fe})!`);return a[b].fe[f.length].apply(this,f)};a[b].fe=[];a[b].fe[e.oe]=e}},Gb=(a,b,c)=>{if(r.hasOwnProperty(a)){if(void 0===c||void 0!==r[a].fe&&void 0!==r[a].fe[c])throw new M(`Cannot register public name '${a}' twice`);Fb(r,a,a);
|
||||
if(r[a].fe.hasOwnProperty(c))throw new M(`Cannot register multiple overloads of a function with the same number of arguments (${c})!`);r[a].fe[c]=b}else r[a]=b,r[a].oe=c},Hb=a=>{a=a.replace(/[^a-zA-Z0-9_]/g,"$");var b=a.charCodeAt(0);return 48<=b&&57>=b?`_${a}`:a};function Ib(a,b,c,e,f,k,n,l){this.name=a;this.constructor=b;this.se=c;this.ne=e;this.ge=f;this.ff=k;this.ye=n;this.cf=l;this.pf=[]}
|
||||
var Jb=(a,b,c)=>{for(;b!==c;){if(!b.ye)throw new M(`Expected null or instance of ${c.name}, got an instance of ${b.name}`);a=b.ye(a);b=b.ge}return a};function Kb(a,b){if(null===b){if(this.Ke)throw new M(`null is not a valid ${this.name}`);return 0}if(!b.Yd)throw new M(`Cannot pass "${Lb(b)}" as a ${this.name}`);if(!b.Yd.ae)throw new M(`Cannot pass deleted object as a pointer of type ${this.name}`);return Jb(b.Yd.ae,b.Yd.de.be,this.be)}
|
||||
function Mb(a,b){if(null===b){if(this.Ke)throw new M(`null is not a valid ${this.name}`);if(this.De){var c=this.Le();null!==a&&a.push(this.ne,c);return c}return 0}if(!b||!b.Yd)throw new M(`Cannot pass "${Lb(b)}" as a ${this.name}`);if(!b.Yd.ae)throw new M(`Cannot pass deleted object as a pointer of type ${this.name}`);if(!this.Ce&&b.Yd.de.Ce)throw new M(`Cannot convert argument of type ${b.Yd.ie?b.Yd.ie.name:b.Yd.de.name} to parameter type ${this.name}`);c=Jb(b.Yd.ae,b.Yd.de.be,this.be);if(this.De){if(void 0===
|
||||
b.Yd.ee)throw new M("Passing raw pointer to smart pointer is illegal");switch(this.uf){case 0:if(b.Yd.ie===this)c=b.Yd.ee;else throw new M(`Cannot convert argument of type ${b.Yd.ie?b.Yd.ie.name:b.Yd.de.name} to parameter type ${this.name}`);break;case 1:c=b.Yd.ee;break;case 2:if(b.Yd.ie===this)c=b.Yd.ee;else{var e=b.clone();c=this.qf(c,Nb(()=>e["delete"]()));null!==a&&a.push(this.ne,c)}break;default:throw new M("Unsupporting sharing policy");}}return c}
|
||||
function Ob(a,b){if(null===b){if(this.Ke)throw new M(`null is not a valid ${this.name}`);return 0}if(!b.Yd)throw new M(`Cannot pass "${Lb(b)}" as a ${this.name}`);if(!b.Yd.ae)throw new M(`Cannot pass deleted object as a pointer of type ${this.name}`);if(b.Yd.de.Ce)throw new M(`Cannot convert argument of type ${b.Yd.de.name} to parameter type ${this.name}`);return Jb(b.Yd.ae,b.Yd.de.be,this.be)}
|
||||
function Pb(a,b,c,e,f,k,n,l,p,v,w){this.name=a;this.be=b;this.Ke=c;this.Ce=e;this.De=f;this.nf=k;this.uf=n;this.Se=l;this.Le=p;this.qf=v;this.ne=w;f||void 0!==b.ge?this.toWireType=Mb:(this.toWireType=e?Kb:Ob,this.ke=null)}
|
||||
var Qb=(a,b,c)=>{if(!r.hasOwnProperty(a))throw new jb("Replacing nonexistent public symbol");void 0!==r[a].fe&&void 0!==c?r[a].fe[c]=b:(r[a]=b,r[a].oe=c)},O,Rb=(a,b,c=[])=>{a.includes("j")?(a=a.replace(/p/g,"i"),b=(0,r["dynCall_"+a])(b,...c)):b=O.get(b)(...c);return b},Sb=(a,b)=>(...c)=>Rb(a,b,c),Tb=(a,b)=>{a=L(a);var c=a.includes("j")?Sb(a,b):O.get(b);if("function"!=typeof c)throw new M(`unknown function pointer with signature ${a}: ${b}`);return c},ac,dc=a=>{a=bc(a);var b=L(a);cc(a);return b},ec=
|
||||
(a,b)=>{function c(k){f[k]||hb[k]||(ib[k]?ib[k].forEach(c):(e.push(k),f[k]=!0))}var e=[],f={};b.forEach(c);throw new ac(`${a}: `+e.map(dc).join([", "]));};function fc(a){for(var b=1;b<a.length;++b)if(null!==a[b]&&void 0===a[b].ke)return!0;return!1}
|
||||
function gc(a,b,c,e,f){var k=b.length;if(2>k)throw new M("argTypes array size mismatch! Must at least get return value and 'this' types!");var n=null!==b[1]&&null!==c,l=fc(b),p="void"!==b[0].name,v=k-2,w=Array(v),A=[],D=[];return Eb(a,function(...I){D.length=0;A.length=n?2:1;A[0]=f;if(n){var R=b[1].toWireType(D,this);A[1]=R}for(var P=0;P<v;++P)w[P]=b[P+2].toWireType(D,I[P]),A.push(w[P]);I=e(...A);if(l)eb(D);else for(P=n?1:2;P<b.length;P++){var ba=1===P?R:w[P-2];null!==b[P].ke&&b[P].ke(ba)}R=p?b[0].fromWireType(I):
|
||||
void 0;return R})}
|
||||
var hc=(a,b)=>{for(var c=[],e=0;e<a;e++)c.push(H[b+4*e>>2]);return c},ic=a=>{a=a.trim();const b=a.indexOf("(");return-1!==b?a.substr(0,b):a},jc=[],kc=[],lc=a=>{9<a&&0===--kc[a+1]&&(kc[a]=void 0,jc.push(a))},mc=a=>{if(!a)throw new M("Cannot use deleted val. handle = "+a);return kc[a]},Nb=a=>{switch(a){case void 0:return 2;case null:return 4;case !0:return 6;case !1:return 8;default:const b=jc.pop()||kc.length;kc[b]=a;kc[b+1]=1;return b}},nc={name:"emscripten::val",fromWireType:a=>{var b=mc(a);lc(a);
|
||||
return b},toWireType:(a,b)=>Nb(b),je:8,readValueFromPointer:fb,ke:null},oc=(a,b,c)=>{switch(b){case 1:return c?function(e){return this.fromWireType(Ca[e])}:function(e){return this.fromWireType(B[e])};case 2:return c?function(e){return this.fromWireType(Da[e>>1])}:function(e){return this.fromWireType(Fa[e>>1])};case 4:return c?function(e){return this.fromWireType(E[e>>2])}:function(e){return this.fromWireType(H[e>>2])};default:throw new TypeError(`invalid integer width (${b}): ${a}`);}},pc=(a,b)=>
|
||||
{var c=hb[a];if(void 0===c)throw a=`${b} has unknown type ${dc(a)}`,new M(a);return c},Lb=a=>{if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a},qc=(a,b)=>{switch(b){case 4:return function(c){return this.fromWireType(J[c>>2])};case 8:return function(c){return this.fromWireType(Ga[c>>3])};default:throw new TypeError(`invalid float width (${b}): ${a}`);}},rc=(a,b,c)=>{switch(b){case 1:return c?e=>Ca[e]:e=>B[e];case 2:return c?e=>Da[e>>1]:e=>Fa[e>>
|
||||
1];case 4:return c?e=>E[e>>2]:e=>H[e>>2];default:throw new TypeError(`invalid integer width (${b}): ${a}`);}},ra=(a,b,c)=>{var e=B;if(!(0<c))return 0;var f=b;c=b+c-1;for(var k=0;k<a.length;++k){var n=a.charCodeAt(k);if(55296<=n&&57343>=n){var l=a.charCodeAt(++k);n=65536+((n&1023)<<10)|l&1023}if(127>=n){if(b>=c)break;e[b++]=n}else{if(2047>=n){if(b+1>=c)break;e[b++]=192|n>>6}else{if(65535>=n){if(b+2>=c)break;e[b++]=224|n>>12}else{if(b+3>=c)break;e[b++]=240|n>>18;e[b++]=128|n>>12&63}e[b++]=128|n>>6&
|
||||
63}e[b++]=128|n&63}}e[b]=0;return b-f},qa=a=>{for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);127>=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++c):b+=3}return b},sc="undefined"!=typeof TextDecoder?new TextDecoder("utf-16le"):void 0,tc=(a,b)=>{var c=a>>1;for(var e=c+b/2;!(c>=e)&&Fa[c];)++c;c<<=1;if(32<c-a&&sc)return sc.decode(B.subarray(a,c));c="";for(e=0;!(e>=b/2);++e){var f=Da[a+2*e>>1];if(0==f)break;c+=String.fromCharCode(f)}return c},uc=(a,b,c)=>{c??=2147483647;if(2>c)return 0;c-=2;var e=
|
||||
b;c=c<2*a.length?c/2:a.length;for(var f=0;f<c;++f)Da[b>>1]=a.charCodeAt(f),b+=2;Da[b>>1]=0;return b-e},vc=a=>2*a.length,wc=(a,b)=>{for(var c=0,e="";!(c>=b/4);){var f=E[a+4*c>>2];if(0==f)break;++c;65536<=f?(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023)):e+=String.fromCharCode(f)}return e},xc=(a,b,c)=>{c??=2147483647;if(4>c)return 0;var e=b;c=e+c-4;for(var f=0;f<a.length;++f){var k=a.charCodeAt(f);if(55296<=k&&57343>=k){var n=a.charCodeAt(++f);k=65536+((k&1023)<<10)|n&1023}E[b>>2]=k;b+=
|
||||
4;if(b+4>c)break}E[b>>2]=0;return b-e},yc=a=>{for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);55296<=e&&57343>=e&&++c;b+=4}return b},zc=(a,b,c)=>{var e=[];a=a.toWireType(e,c);e.length&&(H[b>>2]=Nb(e));return a},Ac=[],Bc={},Cc=a=>{var b=Bc[a];return void 0===b?L(a):b},Dc=()=>{function a(b){b.$$$embind_global$$$=b;var c="object"==typeof $$$embind_global$$$&&b.$$$embind_global$$$==b;c||delete b.$$$embind_global$$$;return c}if("object"==typeof globalThis)return globalThis;if("object"==typeof $$$embind_global$$$)return $$$embind_global$$$;
|
||||
"object"==typeof global&&a(global)?$$$embind_global$$$=global:"object"==typeof self&&a(self)&&($$$embind_global$$$=self);if("object"==typeof $$$embind_global$$$)return $$$embind_global$$$;throw Error("unable to get global object.");},Ec=a=>{var b=Ac.length;Ac.push(a);return b},Fc=(a,b)=>{for(var c=Array(a),e=0;e<a;++e)c[e]=pc(H[b+4*e>>2],"parameter "+e);return c},Gc=Reflect.construct,Q,Hc=a=>{var b=a.getExtension("ANGLE_instanced_arrays");b&&(a.vertexAttribDivisor=(c,e)=>b.vertexAttribDivisorANGLE(c,
|
||||
e),a.drawArraysInstanced=(c,e,f,k)=>b.drawArraysInstancedANGLE(c,e,f,k),a.drawElementsInstanced=(c,e,f,k,n)=>b.drawElementsInstancedANGLE(c,e,f,k,n))},Ic=a=>{var b=a.getExtension("OES_vertex_array_object");b&&(a.createVertexArray=()=>b.createVertexArrayOES(),a.deleteVertexArray=c=>b.deleteVertexArrayOES(c),a.bindVertexArray=c=>b.bindVertexArrayOES(c),a.isVertexArray=c=>b.isVertexArrayOES(c))},Jc=a=>{var b=a.getExtension("WEBGL_draw_buffers");b&&(a.drawBuffers=(c,e)=>b.drawBuffersWEBGL(c,e))},Kc=a=>
|
||||
{var b="ANGLE_instanced_arrays EXT_blend_minmax EXT_disjoint_timer_query EXT_frag_depth EXT_shader_texture_lod EXT_sRGB OES_element_index_uint OES_fbo_render_mipmap OES_standard_derivatives OES_texture_float OES_texture_half_float OES_texture_half_float_linear OES_vertex_array_object WEBGL_color_buffer_float WEBGL_depth_texture WEBGL_draw_buffers EXT_color_buffer_float EXT_conservative_depth EXT_disjoint_timer_query_webgl2 EXT_texture_norm16 NV_shader_noperspective_interpolation WEBGL_clip_cull_distance EXT_clip_control EXT_color_buffer_half_float EXT_depth_clamp EXT_float_blend EXT_polygon_offset_clamp EXT_texture_compression_bptc EXT_texture_compression_rgtc EXT_texture_filter_anisotropic KHR_parallel_shader_compile OES_texture_float_linear WEBGL_blend_func_extended WEBGL_compressed_texture_astc WEBGL_compressed_texture_etc WEBGL_compressed_texture_etc1 WEBGL_compressed_texture_s3tc WEBGL_compressed_texture_s3tc_srgb WEBGL_debug_renderer_info WEBGL_debug_shaders WEBGL_lose_context WEBGL_multi_draw WEBGL_polygon_mode".split(" ");
|
||||
return(a.getSupportedExtensions()||[]).filter(c=>b.includes(c))},Lc=1,Mc=[],Nc=[],Oc=[],Pc=[],ka=[],Qc=[],Rc=[],pa=[],Sc=[],Tc=[],Uc=[],Vc={},Xc={},Yc=4,Zc=0,ja=a=>{for(var b=Lc++,c=a.length;c<b;c++)a[c]=null;return b},$c=(a,b,c,e)=>{for(var f=0;f<a;f++){var k=Q[c](),n=k&&ja(e);k?(k.name=n,e[n]=k):S||=1282;E[b+4*f>>2]=n}},la=(a,b)=>{a.Ne||(a.Ne=a.getContext,a.getContext=function(e,f){f=a.Ne(e,f);return"webgl"==e==f instanceof WebGLRenderingContext?f:null});var c=1<b.majorVersion?a.getContext("webgl2",
|
||||
b):a.getContext("webgl",b);return c?ad(c,b):0},ad=(a,b)=>{var c=ja(pa),e={handle:c,attributes:b,version:b.majorVersion,le:a};a.canvas&&(a.canvas.Ve=e);pa[c]=e;("undefined"==typeof b.df||b.df)&&bd(e);return c},oa=a=>{z=pa[a];r.vf=Q=z?.le;return!(a&&!Q)},bd=a=>{a||=z;if(!a.mf){a.mf=!0;var b=a.le;b.zf=b.getExtension("WEBGL_multi_draw");b.xf=b.getExtension("EXT_polygon_offset_clamp");b.wf=b.getExtension("EXT_clip_control");b.Bf=b.getExtension("WEBGL_polygon_mode");Hc(b);Ic(b);Jc(b);b.Pe=b.getExtension("WEBGL_draw_instanced_base_vertex_base_instance");
|
||||
b.Re=b.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance");2<=a.version&&(b.me=b.getExtension("EXT_disjoint_timer_query_webgl2"));if(2>a.version||!b.me)b.me=b.getExtension("EXT_disjoint_timer_query");Kc(b).forEach(c=>{c.includes("lose_context")||c.includes("debug")||b.getExtension(c)})}},z,S,cd=(a,b)=>{Q.bindFramebuffer(a,Oc[b])},dd=a=>{Q.bindVertexArray(Rc[a])},ed=a=>Q.clear(a),fd=(a,b,c,e)=>Q.clearColor(a,b,c,e),gd=a=>Q.clearStencil(a),hd=(a,b)=>{for(var c=0;c<a;c++){var e=E[b+
|
||||
4*c>>2];Q.deleteVertexArray(Rc[e]);Rc[e]=null}},jd=[],kd=(a,b)=>{$c(a,b,"createVertexArray",Rc)};function ld(){var a=Kc(Q);return a=a.concat(a.map(b=>"GL_"+b))}
|
||||
var md=(a,b,c)=>{if(b){var e=void 0;switch(a){case 36346:e=1;break;case 36344:0!=c&&1!=c&&(S||=1280);return;case 34814:case 36345:e=0;break;case 34466:var f=Q.getParameter(34467);e=f?f.length:0;break;case 33309:if(2>z.version){S||=1282;return}e=ld().length;break;case 33307:case 33308:if(2>z.version){S||=1280;return}e=33307==a?3:0}if(void 0===e)switch(f=Q.getParameter(a),typeof f){case "number":e=f;break;case "boolean":e=f?1:0;break;case "string":S||=1280;return;case "object":if(null===f)switch(a){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:e=
|
||||
0;break;default:S||=1280;return}else{if(f instanceof Float32Array||f instanceof Uint32Array||f instanceof Int32Array||f instanceof Array){for(a=0;a<f.length;++a)switch(c){case 0:E[b+4*a>>2]=f[a];break;case 2:J[b+4*a>>2]=f[a];break;case 4:Ca[b+a]=f[a]?1:0}return}try{e=f.name|0}catch(k){S||=1280;ya(`GL_INVALID_ENUM in glGet${c}v: Unknown object returned from WebGL getParameter(${a})! (error: ${k})`);return}}break;default:S||=1280;ya(`GL_INVALID_ENUM in glGet${c}v: Native code calling glGet${c}v(${a}) and it returns ${f} of type ${typeof f}!`);
|
||||
return}switch(c){case 1:c=e;H[b>>2]=c;H[b+4>>2]=(c-H[b>>2])/4294967296;break;case 0:E[b>>2]=e;break;case 2:J[b>>2]=e;break;case 4:Ca[b]=e?1:0}}else S||=1281},nd=(a,b)=>md(a,b,0),od=(a,b,c)=>{if(c){a=Sc[a];b=2>z.version?Q.me.getQueryObjectEXT(a,b):Q.getQueryParameter(a,b);var e;"boolean"==typeof b?e=b?1:0:e=b;H[c>>2]=e;H[c+4>>2]=(e-H[c>>2])/4294967296}else S||=1281},qd=a=>{var b=qa(a)+1,c=pd(b);c&&ra(a,c,b);return c},rd=a=>{var b=Vc[a];if(!b){switch(a){case 7939:b=qd(ld().join(" "));break;case 7936:case 7937:case 37445:case 37446:(b=
|
||||
Q.getParameter(a))||(S||=1280);b=b?qd(b):0;break;case 7938:b=Q.getParameter(7938);var c=`OpenGL ES 2.0 (${b})`;2<=z.version&&(c=`OpenGL ES 3.0 (${b})`);b=qd(c);break;case 35724:b=Q.getParameter(35724);c=b.match(/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/);null!==c&&(3==c[1].length&&(c[1]+="0"),b=`OpenGL ES GLSL ES ${c[1]} (${b})`);b=qd(b);break;default:S||=1280}Vc[a]=b}return b},sd=(a,b)=>{if(2>z.version)return S||=1282,0;var c=Xc[a];if(c)return 0>b||b>=c.length?(S||=1281,0):c[b];switch(a){case 7939:return c=
|
||||
ld().map(qd),c=Xc[a]=c,0>b||b>=c.length?(S||=1281,0):c[b];default:return S||=1280,0}},td=a=>"]"==a.slice(-1)&&a.lastIndexOf("["),ud=a=>{a-=5120;return 0==a?Ca:1==a?B:2==a?Da:4==a?E:6==a?J:5==a||28922==a||28520==a||30779==a||30782==a?H:Fa},vd=(a,b,c,e,f)=>{a=ud(a);b=e*((Zc||c)*({5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4}[b-6402]||1)*a.BYTES_PER_ELEMENT+Yc-1&-Yc);return a.subarray(f>>>31-Math.clz32(a.BYTES_PER_ELEMENT),f+b>>>31-Math.clz32(a.BYTES_PER_ELEMENT))},V=a=>{var b=Q.bf;if(b){var c=
|
||||
b.xe[a];"number"==typeof c&&(b.xe[a]=c=Q.getUniformLocation(b,b.Te[a]+(0<c?`[${c}]`:"")));return c}S||=1282},wd=[],xd=[],yd={},Ad=()=>{if(!zd){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:"./this.program"},b;for(b in yd)void 0===yd[b]?delete a[b]:a[b]=yd[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);zd=c}return zd},zd,Bd=[null,[],[]];
|
||||
jb=r.InternalError=class extends Error{constructor(a){super(a);this.name="InternalError"}};for(var Cd=Array(256),Dd=0;256>Dd;++Dd)Cd[Dd]=String.fromCharCode(Dd);mb=Cd;M=r.BindingError=class extends Error{constructor(a){super(a);this.name="BindingError"}};
|
||||
Object.assign(Db.prototype,{isAliasOf:function(a){if(!(this instanceof Db&&a instanceof Db))return!1;var b=this.Yd.de.be,c=this.Yd.ae;a.Yd=a.Yd;var e=a.Yd.de.be;for(a=a.Yd.ae;b.ge;)c=b.ye(c),b=b.ge;for(;e.ge;)a=e.ye(a),e=e.ge;return b===e&&c===a},clone:function(){this.Yd.ae||ob(this);if(this.Yd.we)return this.Yd.count.value+=1,this;var a=Ab,b=Object,c=b.create,e=Object.getPrototypeOf(this),f=this.Yd;a=a(c.call(b,e,{Yd:{value:{count:f.count,ve:f.ve,we:f.we,ae:f.ae,de:f.de,ee:f.ee,ie:f.ie}}}));a.Yd.count.value+=
|
||||
1;a.Yd.ve=!1;return a},["delete"](){this.Yd.ae||ob(this);if(this.Yd.ve&&!this.Yd.we)throw new M("Object already scheduled for deletion");qb(this);var a=this.Yd;--a.count.value;0===a.count.value&&(a.ee?a.ie.ne(a.ee):a.de.be.ne(a.ae));this.Yd.we||(this.Yd.ee=void 0,this.Yd.ae=void 0)},isDeleted:function(){return!this.Yd.ae},deleteLater:function(){this.Yd.ae||ob(this);if(this.Yd.ve&&!this.Yd.we)throw new M("Object already scheduled for deletion");Cb.push(this);this.Yd.ve=!0;return this}});
|
||||
Object.assign(Pb.prototype,{gf(a){this.Se&&(a=this.Se(a));return a},Oe(a){this.ne?.(a)},je:8,readValueFromPointer:fb,fromWireType:function(a){function b(){return this.De?Bb(this.be.se,{de:this.nf,ae:c,ie:this,ee:a}):Bb(this.be.se,{de:this,ae:a})}var c=this.gf(a);if(!c)return this.Oe(a),null;var e=zb(this.be,c);if(void 0!==e){if(0===e.Yd.count.value)return e.Yd.ae=c,e.Yd.ee=a,e.clone();e=e.clone();this.Oe(a);return e}e=this.be.ff(c);e=sb[e];if(!e)return b.call(this);e=this.Ce?e.af:e.pointerType;var f=
|
||||
rb(c,this.be,e.be);return null===f?b.call(this):this.De?Bb(e.be.se,{de:e,ae:f,ie:this,ee:a}):Bb(e.be.se,{de:e,ae:f})}});ac=r.UnboundTypeError=((a,b)=>{var c=Eb(b,function(e){this.name=b;this.message=e;e=Error(e).stack;void 0!==e&&(this.stack=this.toString()+"\n"+e.replace(/^Error(:[^\n]*)?\n/,""))});c.prototype=Object.create(a.prototype);c.prototype.constructor=c;c.prototype.toString=function(){return void 0===this.message?this.name:`${this.name}: ${this.message}`};return c})(Error,"UnboundTypeError");
|
||||
kc.push(0,1,void 0,1,null,1,!0,1,!1,1);r.count_emval_handles=()=>kc.length/2-5-jc.length;for(var Ed=0;32>Ed;++Ed)jd.push(Array(Ed));var Fd=new Float32Array(288);for(Ed=0;288>=Ed;++Ed)wd[Ed]=Fd.subarray(0,Ed);var Gd=new Int32Array(288);for(Ed=0;288>=Ed;++Ed)xd[Ed]=Gd.subarray(0,Ed);
|
||||
var Vd={F:(a,b,c)=>{var e=new Xa(a);H[e.ae+16>>2]=0;H[e.ae+4>>2]=b;H[e.ae+8>>2]=c;Ya=a;Za++;throw Ya;},V:function(){return 0},vd:()=>{},ud:function(){return 0},td:()=>{},sd:()=>{},U:function(){},rd:()=>{},nd:()=>{Pa("")},B:a=>{var b=db[a];delete db[a];var c=b.Le,e=b.ne,f=b.Qe,k=f.map(n=>n.kf).concat(f.map(n=>n.sf));lb([a],k,n=>{var l={};f.forEach((p,v)=>{var w=n[v],A=p.hf,D=p.jf,I=n[v+f.length],R=p.rf,P=p.tf;l[p.ef]={read:ba=>w.fromWireType(A(D,ba)),write:(ba,ma)=>{var Y=[];R(P,ba,I.toWireType(Y,
|
||||
ma));eb(Y)}}});return[{name:b.name,fromWireType:p=>{var v={},w;for(w in l)v[w]=l[w].read(p);e(p);return v},toWireType:(p,v)=>{for(var w in l)if(!(w in v))throw new TypeError(`Missing field: "${w}"`);var A=c();for(w in l)l[w].write(A,v[w]);null!==p&&p.push(e,A);return A},je:8,readValueFromPointer:fb,ke:e}]})},Y:()=>{},md:(a,b,c,e)=>{b=L(b);kb(a,{name:b,fromWireType:function(f){return!!f},toWireType:function(f,k){return k?c:e},je:8,readValueFromPointer:function(f){return this.fromWireType(B[f])},ke:null})},
|
||||
l:(a,b,c,e,f,k,n,l,p,v,w,A,D)=>{w=L(w);k=Tb(f,k);l&&=Tb(n,l);v&&=Tb(p,v);D=Tb(A,D);var I=Hb(w);Gb(I,function(){ec(`Cannot construct ${w} due to unbound types`,[e])});lb([a,b,c],e?[e]:[],R=>{R=R[0];if(e){var P=R.be;var ba=P.se}else ba=Db.prototype;R=Eb(w,function(...Ea){if(Object.getPrototypeOf(this)!==ma)throw new M("Use 'new' to construct "+w);if(void 0===Y.pe)throw new M(w+" has no accessible constructor");var fa=Y.pe[Ea.length];if(void 0===fa)throw new M(`Tried to invoke ctor of ${w} with invalid number of parameters (${Ea.length}) - expected (${Object.keys(Y.pe).toString()}) parameters instead!`);
|
||||
return fa.apply(this,Ea)});var ma=Object.create(ba,{constructor:{value:R}});R.prototype=ma;var Y=new Ib(w,R,ma,D,P,k,l,v);if(Y.ge){var ia;(ia=Y.ge).ze??(ia.ze=[]);Y.ge.ze.push(Y)}P=new Pb(w,Y,!0,!1,!1);ia=new Pb(w+"*",Y,!1,!1,!1);ba=new Pb(w+" const*",Y,!1,!0,!1);sb[a]={pointerType:ia,af:ba};Qb(I,R);return[P,ia,ba]})},e:(a,b,c,e,f,k,n)=>{var l=hc(c,e);b=L(b);b=ic(b);k=Tb(f,k);lb([],[a],p=>{function v(){ec(`Cannot call ${w} due to unbound types`,l)}p=p[0];var w=`${p.name}.${b}`;b.startsWith("@@")&&
|
||||
(b=Symbol[b.substring(2)]);var A=p.be.constructor;void 0===A[b]?(v.oe=c-1,A[b]=v):(Fb(A,b,w),A[b].fe[c-1]=v);lb([],l,D=>{D=[D[0],null].concat(D.slice(1));D=gc(w,D,null,k,n);void 0===A[b].fe?(D.oe=c-1,A[b]=D):A[b].fe[c-1]=D;if(p.be.ze)for(const I of p.be.ze)I.constructor.hasOwnProperty(b)||(I.constructor[b]=D);return[]});return[]})},z:(a,b,c,e,f,k)=>{var n=hc(b,c);f=Tb(e,f);lb([],[a],l=>{l=l[0];var p=`constructor ${l.name}`;void 0===l.be.pe&&(l.be.pe=[]);if(void 0!==l.be.pe[b-1])throw new M(`Cannot register multiple constructors with identical number of parameters (${b-
|
||||
1}) for class '${l.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`);l.be.pe[b-1]=()=>{ec(`Cannot construct ${l.name} due to unbound types`,n)};lb([],n,v=>{v.splice(1,0,null);l.be.pe[b-1]=gc(p,v,null,f,k);return[]});return[]})},a:(a,b,c,e,f,k,n,l)=>{var p=hc(c,e);b=L(b);b=ic(b);k=Tb(f,k);lb([],[a],v=>{function w(){ec(`Cannot call ${A} due to unbound types`,p)}v=v[0];var A=`${v.name}.${b}`;b.startsWith("@@")&&(b=Symbol[b.substring(2)]);l&&v.be.pf.push(b);
|
||||
var D=v.be.se,I=D[b];void 0===I||void 0===I.fe&&I.className!==v.name&&I.oe===c-2?(w.oe=c-2,w.className=v.name,D[b]=w):(Fb(D,b,A),D[b].fe[c-2]=w);lb([],p,R=>{R=gc(A,R,v,k,n);void 0===D[b].fe?(R.oe=c-2,D[b]=R):D[b].fe[c-2]=R;return[]});return[]})},q:(a,b,c)=>{a=L(a);lb([],[b],e=>{e=e[0];r[a]=e.fromWireType(c);return[]})},ld:a=>kb(a,nc),j:(a,b,c,e)=>{function f(){}b=L(b);f.values={};kb(a,{name:b,constructor:f,fromWireType:function(k){return this.constructor.values[k]},toWireType:(k,n)=>n.value,je:8,
|
||||
readValueFromPointer:oc(b,c,e),ke:null});Gb(b,f)},b:(a,b,c)=>{var e=pc(a,"enum");b=L(b);a=e.constructor;e=Object.create(e.constructor.prototype,{value:{value:c},constructor:{value:Eb(`${e.name}_${b}`,function(){})}});a.values[c]=e;a[b]=e},S:(a,b,c)=>{b=L(b);kb(a,{name:b,fromWireType:e=>e,toWireType:(e,f)=>f,je:8,readValueFromPointer:qc(b,c),ke:null})},w:(a,b,c,e,f,k)=>{var n=hc(b,c);a=L(a);a=ic(a);f=Tb(e,f);Gb(a,function(){ec(`Cannot call ${a} due to unbound types`,n)},b-1);lb([],n,l=>{l=[l[0],null].concat(l.slice(1));
|
||||
Qb(a,gc(a,l,null,f,k),b-1);return[]})},C:(a,b,c,e,f)=>{b=L(b);-1===f&&(f=4294967295);f=l=>l;if(0===e){var k=32-8*c;f=l=>l<<k>>>k}var n=b.includes("unsigned")?function(l,p){return p>>>0}:function(l,p){return p};kb(a,{name:b,fromWireType:f,toWireType:n,je:8,readValueFromPointer:rc(b,c,0!==e),ke:null})},p:(a,b,c)=>{function e(k){return new f(Ca.buffer,H[k+4>>2],H[k>>2])}var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=L(c);kb(a,{name:c,fromWireType:e,
|
||||
je:8,readValueFromPointer:e},{lf:!0})},o:(a,b,c,e,f,k,n,l,p,v,w,A)=>{c=L(c);k=Tb(f,k);l=Tb(n,l);v=Tb(p,v);A=Tb(w,A);lb([a],[b],D=>{D=D[0];return[new Pb(c,D.be,!1,!1,!0,D,e,k,l,v,A)]})},R:(a,b)=>{b=L(b);var c="std::string"===b;kb(a,{name:b,fromWireType:function(e){var f=H[e>>2],k=e+4;if(c)for(var n=k,l=0;l<=f;++l){var p=k+l;if(l==f||0==B[p]){n=n?cb(B,n,p-n):"";if(void 0===v)var v=n;else v+=String.fromCharCode(0),v+=n;n=p+1}}else{v=Array(f);for(l=0;l<f;++l)v[l]=String.fromCharCode(B[k+l]);v=v.join("")}cc(e);
|
||||
return v},toWireType:function(e,f){f instanceof ArrayBuffer&&(f=new Uint8Array(f));var k="string"==typeof f;if(!(k||f instanceof Uint8Array||f instanceof Uint8ClampedArray||f instanceof Int8Array))throw new M("Cannot pass non-string to std::string");var n=c&&k?qa(f):f.length;var l=pd(4+n+1),p=l+4;H[l>>2]=n;if(c&&k)ra(f,p,n+1);else if(k)for(k=0;k<n;++k){var v=f.charCodeAt(k);if(255<v)throw cc(p),new M("String has UTF-16 code units that do not fit in 8 bits");B[p+k]=v}else for(k=0;k<n;++k)B[p+k]=f[k];
|
||||
null!==e&&e.push(cc,l);return l},je:8,readValueFromPointer:fb,ke(e){cc(e)}})},M:(a,b,c)=>{c=L(c);if(2===b){var e=tc;var f=uc;var k=vc;var n=l=>Fa[l>>1]}else 4===b&&(e=wc,f=xc,k=yc,n=l=>H[l>>2]);kb(a,{name:c,fromWireType:l=>{for(var p=H[l>>2],v,w=l+4,A=0;A<=p;++A){var D=l+4+A*b;if(A==p||0==n(D))w=e(w,D-w),void 0===v?v=w:(v+=String.fromCharCode(0),v+=w),w=D+b}cc(l);return v},toWireType:(l,p)=>{if("string"!=typeof p)throw new M(`Cannot pass non-string to C++ string type ${c}`);var v=k(p),w=pd(4+v+b);
|
||||
H[w>>2]=v/b;f(p,w+4,v+b);null!==l&&l.push(cc,w);return w},je:8,readValueFromPointer:fb,ke(l){cc(l)}})},A:(a,b,c,e,f,k)=>{db[a]={name:L(b),Le:Tb(c,e),ne:Tb(f,k),Qe:[]}},d:(a,b,c,e,f,k,n,l,p,v)=>{db[a].Qe.push({ef:L(b),kf:c,hf:Tb(e,f),jf:k,sf:n,rf:Tb(l,p),tf:v})},kd:(a,b)=>{b=L(b);kb(a,{yf:!0,name:b,je:0,fromWireType:()=>{},toWireType:()=>{}})},jd:()=>1,id:()=>{throw Infinity;},E:(a,b,c)=>{a=mc(a);b=pc(b,"emval::as");return zc(b,c,a)},L:(a,b,c,e)=>{a=Ac[a];b=mc(b);return a(null,b,c,e)},t:(a,b,c,e,f)=>
|
||||
{a=Ac[a];b=mc(b);c=Cc(c);return a(b,b[c],e,f)},c:lc,K:a=>{if(0===a)return Nb(Dc());a=Cc(a);return Nb(Dc()[a])},n:(a,b,c)=>{var e=Fc(a,b),f=e.shift();a--;var k=Array(a);b=`methodCaller<(${e.map(n=>n.name).join(", ")}) => ${f.name}>`;return Ec(Eb(b,(n,l,p,v)=>{for(var w=0,A=0;A<a;++A)k[A]=e[A].readValueFromPointer(v+w),w+=e[A].je;n=1===c?Gc(l,k):l.apply(n,k);return zc(f,p,n)}))},y:(a,b)=>{a=mc(a);b=mc(b);return Nb(a[b])},H:a=>{9<a&&(kc[a+1]+=1)},G:()=>Nb([]),f:a=>Nb(Cc(a)),D:()=>Nb({}),hd:a=>{a=mc(a);
|
||||
return!a},m:a=>{var b=mc(a);eb(b);lc(a)},h:(a,b,c)=>{a=mc(a);b=mc(b);c=mc(c);a[b]=c},g:(a,b)=>{a=pc(a,"_emval_take_value");a=a.readValueFromPointer(b);return Nb(a)},X:function(){return-52},W:function(){},gd:(a,b,c,e)=>{var f=(new Date).getFullYear(),k=(new Date(f,0,1)).getTimezoneOffset();f=(new Date(f,6,1)).getTimezoneOffset();H[a>>2]=60*Math.max(k,f);E[b>>2]=Number(k!=f);b=n=>{var l=Math.abs(n);return`UTC${0<=n?"-":"+"}${String(Math.floor(l/60)).padStart(2,"0")}${String(l%60).padStart(2,"0")}`};
|
||||
a=b(k);b=b(f);f<k?(ra(a,c,17),ra(b,e,17)):(ra(a,e,17),ra(b,c,17))},fd:()=>performance.now(),ed:a=>Q.activeTexture(a),dd:(a,b)=>{Q.attachShader(Nc[a],Qc[b])},cd:(a,b)=>{Q.beginQuery(a,Sc[b])},bd:(a,b)=>{Q.me.beginQueryEXT(a,Sc[b])},ad:(a,b,c)=>{Q.bindAttribLocation(Nc[a],b,c?cb(B,c):"")},$c:(a,b)=>{35051==a?Q.Ie=b:35052==a&&(Q.re=b);Q.bindBuffer(a,Mc[b])},_c:cd,Zc:(a,b)=>{Q.bindRenderbuffer(a,Pc[b])},Yc:(a,b)=>{Q.bindSampler(a,Tc[b])},Xc:(a,b)=>{Q.bindTexture(a,ka[b])},Wc:dd,Vc:dd,Uc:(a,b,c,e)=>Q.blendColor(a,
|
||||
b,c,e),Tc:a=>Q.blendEquation(a),Sc:(a,b)=>Q.blendFunc(a,b),Rc:(a,b,c,e,f,k,n,l,p,v)=>Q.blitFramebuffer(a,b,c,e,f,k,n,l,p,v),Qc:(a,b,c,e)=>{2<=z.version?c&&b?Q.bufferData(a,B,e,c,b):Q.bufferData(a,b,e):Q.bufferData(a,c?B.subarray(c,c+b):b,e)},Pc:(a,b,c,e)=>{2<=z.version?c&&Q.bufferSubData(a,b,B,e,c):Q.bufferSubData(a,b,B.subarray(e,e+c))},Oc:a=>Q.checkFramebufferStatus(a),Nc:ed,Mc:fd,Lc:gd,Kc:(a,b,c,e)=>Q.clientWaitSync(Uc[a],b,(c>>>0)+4294967296*e),Jc:(a,b,c,e)=>{Q.colorMask(!!a,!!b,!!c,!!e)},Ic:a=>
|
||||
{Q.compileShader(Qc[a])},Hc:(a,b,c,e,f,k,n,l)=>{2<=z.version?Q.re||!n?Q.compressedTexImage2D(a,b,c,e,f,k,n,l):Q.compressedTexImage2D(a,b,c,e,f,k,B,l,n):Q.compressedTexImage2D(a,b,c,e,f,k,B.subarray(l,l+n))},Gc:(a,b,c,e,f,k,n,l,p)=>{2<=z.version?Q.re||!l?Q.compressedTexSubImage2D(a,b,c,e,f,k,n,l,p):Q.compressedTexSubImage2D(a,b,c,e,f,k,n,B,p,l):Q.compressedTexSubImage2D(a,b,c,e,f,k,n,B.subarray(p,p+l))},Fc:(a,b,c,e,f)=>Q.copyBufferSubData(a,b,c,e,f),Ec:(a,b,c,e,f,k,n,l)=>Q.copyTexSubImage2D(a,b,c,
|
||||
e,f,k,n,l),Dc:()=>{var a=ja(Nc),b=Q.createProgram();b.name=a;b.Ge=b.Ee=b.Fe=0;b.Me=1;Nc[a]=b;return a},Cc:a=>{var b=ja(Qc);Qc[b]=Q.createShader(a);return b},Bc:a=>Q.cullFace(a),Ac:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Mc[e];f&&(Q.deleteBuffer(f),f.name=0,Mc[e]=null,e==Q.Ie&&(Q.Ie=0),e==Q.re&&(Q.re=0))}},zc:(a,b)=>{for(var c=0;c<a;++c){var e=E[b+4*c>>2],f=Oc[e];f&&(Q.deleteFramebuffer(f),f.name=0,Oc[e]=null)}},yc:a=>{if(a){var b=Nc[a];b?(Q.deleteProgram(b),b.name=0,Nc[a]=null):S||=1281}},
|
||||
xc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Sc[e];f&&(Q.deleteQuery(f),Sc[e]=null)}},wc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Sc[e];f&&(Q.me.deleteQueryEXT(f),Sc[e]=null)}},vc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Pc[e];f&&(Q.deleteRenderbuffer(f),f.name=0,Pc[e]=null)}},uc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Tc[e];f&&(Q.deleteSampler(f),f.name=0,Tc[e]=null)}},tc:a=>{if(a){var b=Qc[a];b?(Q.deleteShader(b),Qc[a]=null):S||=1281}},sc:a=>{if(a){var b=Uc[a];b?
|
||||
(Q.deleteSync(b),b.name=0,Uc[a]=null):S||=1281}},rc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=ka[e];f&&(Q.deleteTexture(f),f.name=0,ka[e]=null)}},qc:hd,pc:hd,oc:a=>{Q.depthMask(!!a)},nc:a=>Q.disable(a),mc:a=>{Q.disableVertexAttribArray(a)},lc:(a,b,c)=>{Q.drawArrays(a,b,c)},kc:(a,b,c,e)=>{Q.drawArraysInstanced(a,b,c,e)},jc:(a,b,c,e,f)=>{Q.Pe.drawArraysInstancedBaseInstanceWEBGL(a,b,c,e,f)},ic:(a,b)=>{for(var c=jd[a],e=0;e<a;e++)c[e]=E[b+4*e>>2];Q.drawBuffers(c)},hc:(a,b,c,e)=>{Q.drawElements(a,
|
||||
b,c,e)},gc:(a,b,c,e,f)=>{Q.drawElementsInstanced(a,b,c,e,f)},fc:(a,b,c,e,f,k,n)=>{Q.Pe.drawElementsInstancedBaseVertexBaseInstanceWEBGL(a,b,c,e,f,k,n)},ec:(a,b,c,e,f,k)=>{Q.drawElements(a,e,f,k)},dc:a=>Q.enable(a),cc:a=>{Q.enableVertexAttribArray(a)},bc:a=>Q.endQuery(a),ac:a=>{Q.me.endQueryEXT(a)},$b:(a,b)=>(a=Q.fenceSync(a,b))?(b=ja(Uc),a.name=b,Uc[b]=a,b):0,_b:()=>Q.finish(),Zb:()=>Q.flush(),Yb:(a,b,c,e)=>{Q.framebufferRenderbuffer(a,b,c,Pc[e])},Xb:(a,b,c,e,f)=>{Q.framebufferTexture2D(a,b,c,ka[e],
|
||||
f)},Wb:a=>Q.frontFace(a),Vb:(a,b)=>{$c(a,b,"createBuffer",Mc)},Ub:(a,b)=>{$c(a,b,"createFramebuffer",Oc)},Tb:(a,b)=>{$c(a,b,"createQuery",Sc)},Sb:(a,b)=>{for(var c=0;c<a;c++){var e=Q.me.createQueryEXT();if(!e){for(S||=1282;c<a;)E[b+4*c++>>2]=0;break}var f=ja(Sc);e.name=f;Sc[f]=e;E[b+4*c>>2]=f}},Rb:(a,b)=>{$c(a,b,"createRenderbuffer",Pc)},Qb:(a,b)=>{$c(a,b,"createSampler",Tc)},Pb:(a,b)=>{$c(a,b,"createTexture",ka)},Ob:kd,Nb:kd,Mb:a=>Q.generateMipmap(a),Lb:(a,b,c)=>{c?E[c>>2]=Q.getBufferParameter(a,
|
||||
b):S||=1281},Kb:()=>{var a=Q.getError()||S;S=0;return a},Jb:(a,b)=>md(a,b,2),Ib:(a,b,c,e)=>{a=Q.getFramebufferAttachmentParameter(a,b,c);if(a instanceof WebGLRenderbuffer||a instanceof WebGLTexture)a=a.name|0;E[e>>2]=a},Hb:nd,Gb:(a,b,c,e)=>{a=Q.getProgramInfoLog(Nc[a]);null===a&&(a="(unknown error)");b=0<b&&e?ra(a,e,b):0;c&&(E[c>>2]=b)},Fb:(a,b,c)=>{if(c)if(a>=Lc)S||=1281;else if(a=Nc[a],35716==b)a=Q.getProgramInfoLog(a),null===a&&(a="(unknown error)"),E[c>>2]=a.length+1;else if(35719==b){if(!a.Ge){var e=
|
||||
Q.getProgramParameter(a,35718);for(b=0;b<e;++b)a.Ge=Math.max(a.Ge,Q.getActiveUniform(a,b).name.length+1)}E[c>>2]=a.Ge}else if(35722==b){if(!a.Ee)for(e=Q.getProgramParameter(a,35721),b=0;b<e;++b)a.Ee=Math.max(a.Ee,Q.getActiveAttrib(a,b).name.length+1);E[c>>2]=a.Ee}else if(35381==b){if(!a.Fe)for(e=Q.getProgramParameter(a,35382),b=0;b<e;++b)a.Fe=Math.max(a.Fe,Q.getActiveUniformBlockName(a,b).length+1);E[c>>2]=a.Fe}else E[c>>2]=Q.getProgramParameter(a,b);else S||=1281},Eb:od,Db:od,Cb:(a,b,c)=>{if(c){a=
|
||||
Q.getQueryParameter(Sc[a],b);var e;"boolean"==typeof a?e=a?1:0:e=a;E[c>>2]=e}else S||=1281},Bb:(a,b,c)=>{if(c){a=Q.me.getQueryObjectEXT(Sc[a],b);var e;"boolean"==typeof a?e=a?1:0:e=a;E[c>>2]=e}else S||=1281},Ab:(a,b,c)=>{c?E[c>>2]=Q.getQuery(a,b):S||=1281},zb:(a,b,c)=>{c?E[c>>2]=Q.me.getQueryEXT(a,b):S||=1281},yb:(a,b,c)=>{c?E[c>>2]=Q.getRenderbufferParameter(a,b):S||=1281},xb:(a,b,c,e)=>{a=Q.getShaderInfoLog(Qc[a]);null===a&&(a="(unknown error)");b=0<b&&e?ra(a,e,b):0;c&&(E[c>>2]=b)},wb:(a,b,c,e)=>
|
||||
{a=Q.getShaderPrecisionFormat(a,b);E[c>>2]=a.rangeMin;E[c+4>>2]=a.rangeMax;E[e>>2]=a.precision},vb:(a,b,c)=>{c?35716==b?(a=Q.getShaderInfoLog(Qc[a]),null===a&&(a="(unknown error)"),E[c>>2]=a?a.length+1:0):35720==b?(a=Q.getShaderSource(Qc[a]),E[c>>2]=a?a.length+1:0):E[c>>2]=Q.getShaderParameter(Qc[a],b):S||=1281},ub:rd,tb:sd,sb:(a,b)=>{b=b?cb(B,b):"";if(a=Nc[a]){var c=a,e=c.xe,f=c.Ue,k;if(!e){c.xe=e={};c.Te={};var n=Q.getProgramParameter(c,35718);for(k=0;k<n;++k){var l=Q.getActiveUniform(c,k);var p=
|
||||
l.name;l=l.size;var v=td(p);v=0<v?p.slice(0,v):p;var w=c.Me;c.Me+=l;f[v]=[l,w];for(p=0;p<l;++p)e[w]=p,c.Te[w++]=v}}c=a.xe;e=0;f=b;k=td(b);0<k&&(e=parseInt(b.slice(k+1))>>>0,f=b.slice(0,k));if((f=a.Ue[f])&&e<f[0]&&(e+=f[1],c[e]=c[e]||Q.getUniformLocation(a,b)))return e}else S||=1281;return-1},rb:(a,b,c)=>{for(var e=jd[b],f=0;f<b;f++)e[f]=E[c+4*f>>2];Q.invalidateFramebuffer(a,e)},qb:(a,b,c,e,f,k,n)=>{for(var l=jd[b],p=0;p<b;p++)l[p]=E[c+4*p>>2];Q.invalidateSubFramebuffer(a,l,e,f,k,n)},pb:a=>Q.isSync(Uc[a]),
|
||||
ob:a=>(a=ka[a])?Q.isTexture(a):0,nb:a=>Q.lineWidth(a),mb:a=>{a=Nc[a];Q.linkProgram(a);a.xe=0;a.Ue={}},lb:(a,b,c,e,f,k)=>{Q.Re.multiDrawArraysInstancedBaseInstanceWEBGL(a,E,b>>2,E,c>>2,E,e>>2,H,f>>2,k)},kb:(a,b,c,e,f,k,n,l)=>{Q.Re.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(a,E,b>>2,c,E,e>>2,E,f>>2,E,k>>2,H,n>>2,l)},jb:(a,b)=>{3317==a?Yc=b:3314==a&&(Zc=b);Q.pixelStorei(a,b)},ib:(a,b)=>{Q.me.queryCounterEXT(Sc[a],b)},hb:a=>Q.readBuffer(a),gb:(a,b,c,e,f,k,n)=>{if(2<=z.version)if(Q.Ie)Q.readPixels(a,
|
||||
b,c,e,f,k,n);else{var l=ud(k);n>>>=31-Math.clz32(l.BYTES_PER_ELEMENT);Q.readPixels(a,b,c,e,f,k,l,n)}else(l=vd(k,f,c,e,n))?Q.readPixels(a,b,c,e,f,k,l):S||=1280},fb:(a,b,c,e)=>Q.renderbufferStorage(a,b,c,e),eb:(a,b,c,e,f)=>Q.renderbufferStorageMultisample(a,b,c,e,f),db:(a,b,c)=>{Q.samplerParameterf(Tc[a],b,c)},cb:(a,b,c)=>{Q.samplerParameteri(Tc[a],b,c)},bb:(a,b,c)=>{Q.samplerParameteri(Tc[a],b,E[c>>2])},ab:(a,b,c,e)=>Q.scissor(a,b,c,e),$a:(a,b,c,e)=>{for(var f="",k=0;k<b;++k){var n=(n=H[c+4*k>>2])?
|
||||
cb(B,n,e?H[e+4*k>>2]:void 0):"";f+=n}Q.shaderSource(Qc[a],f)},_a:(a,b,c)=>Q.stencilFunc(a,b,c),Za:(a,b,c,e)=>Q.stencilFuncSeparate(a,b,c,e),Ya:a=>Q.stencilMask(a),Xa:(a,b)=>Q.stencilMaskSeparate(a,b),Wa:(a,b,c)=>Q.stencilOp(a,b,c),Va:(a,b,c,e)=>Q.stencilOpSeparate(a,b,c,e),Ua:(a,b,c,e,f,k,n,l,p)=>{if(2<=z.version){if(Q.re){Q.texImage2D(a,b,c,e,f,k,n,l,p);return}if(p){var v=ud(l);p>>>=31-Math.clz32(v.BYTES_PER_ELEMENT);Q.texImage2D(a,b,c,e,f,k,n,l,v,p);return}}v=p?vd(l,n,e,f,p):null;Q.texImage2D(a,
|
||||
b,c,e,f,k,n,l,v)},Ta:(a,b,c)=>Q.texParameterf(a,b,c),Sa:(a,b,c)=>{Q.texParameterf(a,b,J[c>>2])},Ra:(a,b,c)=>Q.texParameteri(a,b,c),Qa:(a,b,c)=>{Q.texParameteri(a,b,E[c>>2])},Pa:(a,b,c,e,f)=>Q.texStorage2D(a,b,c,e,f),Oa:(a,b,c,e,f,k,n,l,p)=>{if(2<=z.version){if(Q.re){Q.texSubImage2D(a,b,c,e,f,k,n,l,p);return}if(p){var v=ud(l);Q.texSubImage2D(a,b,c,e,f,k,n,l,v,p>>>31-Math.clz32(v.BYTES_PER_ELEMENT));return}}p=p?vd(l,n,f,k,p):null;Q.texSubImage2D(a,b,c,e,f,k,n,l,p)},Na:(a,b)=>{Q.uniform1f(V(a),b)},Ma:(a,
|
||||
b,c)=>{if(2<=z.version)b&&Q.uniform1fv(V(a),J,c>>2,b);else{if(288>=b)for(var e=wd[b],f=0;f<b;++f)e[f]=J[c+4*f>>2];else e=J.subarray(c>>2,c+4*b>>2);Q.uniform1fv(V(a),e)}},La:(a,b)=>{Q.uniform1i(V(a),b)},Ka:(a,b,c)=>{if(2<=z.version)b&&Q.uniform1iv(V(a),E,c>>2,b);else{if(288>=b)for(var e=xd[b],f=0;f<b;++f)e[f]=E[c+4*f>>2];else e=E.subarray(c>>2,c+4*b>>2);Q.uniform1iv(V(a),e)}},Ja:(a,b,c)=>{Q.uniform2f(V(a),b,c)},Ia:(a,b,c)=>{if(2<=z.version)b&&Q.uniform2fv(V(a),J,c>>2,2*b);else{if(144>=b){b*=2;for(var e=
|
||||
wd[b],f=0;f<b;f+=2)e[f]=J[c+4*f>>2],e[f+1]=J[c+(4*f+4)>>2]}else e=J.subarray(c>>2,c+8*b>>2);Q.uniform2fv(V(a),e)}},Ha:(a,b,c)=>{Q.uniform2i(V(a),b,c)},Ga:(a,b,c)=>{if(2<=z.version)b&&Q.uniform2iv(V(a),E,c>>2,2*b);else{if(144>=b){b*=2;for(var e=xd[b],f=0;f<b;f+=2)e[f]=E[c+4*f>>2],e[f+1]=E[c+(4*f+4)>>2]}else e=E.subarray(c>>2,c+8*b>>2);Q.uniform2iv(V(a),e)}},Fa:(a,b,c,e)=>{Q.uniform3f(V(a),b,c,e)},Ea:(a,b,c)=>{if(2<=z.version)b&&Q.uniform3fv(V(a),J,c>>2,3*b);else{if(96>=b){b*=3;for(var e=wd[b],f=0;f<
|
||||
b;f+=3)e[f]=J[c+4*f>>2],e[f+1]=J[c+(4*f+4)>>2],e[f+2]=J[c+(4*f+8)>>2]}else e=J.subarray(c>>2,c+12*b>>2);Q.uniform3fv(V(a),e)}},Da:(a,b,c,e)=>{Q.uniform3i(V(a),b,c,e)},Ca:(a,b,c)=>{if(2<=z.version)b&&Q.uniform3iv(V(a),E,c>>2,3*b);else{if(96>=b){b*=3;for(var e=xd[b],f=0;f<b;f+=3)e[f]=E[c+4*f>>2],e[f+1]=E[c+(4*f+4)>>2],e[f+2]=E[c+(4*f+8)>>2]}else e=E.subarray(c>>2,c+12*b>>2);Q.uniform3iv(V(a),e)}},Ba:(a,b,c,e,f)=>{Q.uniform4f(V(a),b,c,e,f)},Aa:(a,b,c)=>{if(2<=z.version)b&&Q.uniform4fv(V(a),J,c>>2,4*
|
||||
b);else{if(72>=b){var e=wd[4*b],f=J;c>>=2;b*=4;for(var k=0;k<b;k+=4){var n=c+k;e[k]=f[n];e[k+1]=f[n+1];e[k+2]=f[n+2];e[k+3]=f[n+3]}}else e=J.subarray(c>>2,c+16*b>>2);Q.uniform4fv(V(a),e)}},za:(a,b,c,e,f)=>{Q.uniform4i(V(a),b,c,e,f)},ya:(a,b,c)=>{if(2<=z.version)b&&Q.uniform4iv(V(a),E,c>>2,4*b);else{if(72>=b){b*=4;for(var e=xd[b],f=0;f<b;f+=4)e[f]=E[c+4*f>>2],e[f+1]=E[c+(4*f+4)>>2],e[f+2]=E[c+(4*f+8)>>2],e[f+3]=E[c+(4*f+12)>>2]}else e=E.subarray(c>>2,c+16*b>>2);Q.uniform4iv(V(a),e)}},xa:(a,b,c,e)=>
|
||||
{if(2<=z.version)b&&Q.uniformMatrix2fv(V(a),!!c,J,e>>2,4*b);else{if(72>=b){b*=4;for(var f=wd[b],k=0;k<b;k+=4)f[k]=J[e+4*k>>2],f[k+1]=J[e+(4*k+4)>>2],f[k+2]=J[e+(4*k+8)>>2],f[k+3]=J[e+(4*k+12)>>2]}else f=J.subarray(e>>2,e+16*b>>2);Q.uniformMatrix2fv(V(a),!!c,f)}},wa:(a,b,c,e)=>{if(2<=z.version)b&&Q.uniformMatrix3fv(V(a),!!c,J,e>>2,9*b);else{if(32>=b){b*=9;for(var f=wd[b],k=0;k<b;k+=9)f[k]=J[e+4*k>>2],f[k+1]=J[e+(4*k+4)>>2],f[k+2]=J[e+(4*k+8)>>2],f[k+3]=J[e+(4*k+12)>>2],f[k+4]=J[e+(4*k+16)>>2],f[k+
|
||||
5]=J[e+(4*k+20)>>2],f[k+6]=J[e+(4*k+24)>>2],f[k+7]=J[e+(4*k+28)>>2],f[k+8]=J[e+(4*k+32)>>2]}else f=J.subarray(e>>2,e+36*b>>2);Q.uniformMatrix3fv(V(a),!!c,f)}},va:(a,b,c,e)=>{if(2<=z.version)b&&Q.uniformMatrix4fv(V(a),!!c,J,e>>2,16*b);else{if(18>=b){var f=wd[16*b],k=J;e>>=2;b*=16;for(var n=0;n<b;n+=16){var l=e+n;f[n]=k[l];f[n+1]=k[l+1];f[n+2]=k[l+2];f[n+3]=k[l+3];f[n+4]=k[l+4];f[n+5]=k[l+5];f[n+6]=k[l+6];f[n+7]=k[l+7];f[n+8]=k[l+8];f[n+9]=k[l+9];f[n+10]=k[l+10];f[n+11]=k[l+11];f[n+12]=k[l+12];f[n+
|
||||
13]=k[l+13];f[n+14]=k[l+14];f[n+15]=k[l+15]}}else f=J.subarray(e>>2,e+64*b>>2);Q.uniformMatrix4fv(V(a),!!c,f)}},ua:a=>{a=Nc[a];Q.useProgram(a);Q.bf=a},ta:(a,b)=>Q.vertexAttrib1f(a,b),sa:(a,b)=>{Q.vertexAttrib2f(a,J[b>>2],J[b+4>>2])},ra:(a,b)=>{Q.vertexAttrib3f(a,J[b>>2],J[b+4>>2],J[b+8>>2])},qa:(a,b)=>{Q.vertexAttrib4f(a,J[b>>2],J[b+4>>2],J[b+8>>2],J[b+12>>2])},pa:(a,b)=>{Q.vertexAttribDivisor(a,b)},oa:(a,b,c,e,f)=>{Q.vertexAttribIPointer(a,b,c,e,f)},na:(a,b,c,e,f,k)=>{Q.vertexAttribPointer(a,b,c,
|
||||
!!e,f,k)},ma:(a,b,c,e)=>Q.viewport(a,b,c,e),la:(a,b,c,e)=>{Q.waitSync(Uc[a],b,(c>>>0)+4294967296*e)},ka:a=>{var b=B.length;a>>>=0;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+1/c);e=Math.min(e,a+100663296);a:{e=(Math.min(2147483648,65536*Math.ceil(Math.max(a,e)/65536))-za.buffer.byteLength+65535)/65536|0;try{za.grow(e);Ha();var f=1;break a}catch(k){}f=void 0}if(f)return!0}return!1},ja:()=>z?z.handle:0,qd:(a,b)=>{var c=0;Ad().forEach((e,f)=>{var k=b+c;f=H[a+4*f>>2]=k;for(k=0;k<e.length;++k)Ca[f++]=
|
||||
e.charCodeAt(k);Ca[f]=0;c+=e.length+1});return 0},pd:(a,b)=>{var c=Ad();H[a>>2]=c.length;var e=0;c.forEach(f=>e+=f.length+1);H[b>>2]=e;return 0},ia:a=>{throw new Va(a);},N:()=>52,_:function(){return 52},od:()=>52,Z:function(){return 70},T:(a,b,c,e)=>{for(var f=0,k=0;k<c;k++){var n=H[b>>2],l=H[b+4>>2];b+=8;for(var p=0;p<l;p++){var v=B[n+p],w=Bd[a];0===v||10===v?((1===a?wa:ya)(cb(w)),w.length=0):w.push(v)}f+=l}H[e>>2]=f;return 0},ha:cd,ga:ed,fa:fd,ea:gd,J:nd,Q:rd,da:sd,k:Hd,u:Id,i:Jd,I:Kd,ca:Ld,P:Md,
|
||||
O:Nd,s:Od,x:Pd,r:Qd,v:Rd,ba:Sd,aa:Td,$:Ud},Z=function(){var a={a:Vd};La++;Ra??=r.locateFile?Qa("canvaskit.wasm")?"canvaskit.wasm":ta+"canvaskit.wasm":(new URL("canvaskit.wasm",import.meta.url)).href;Ua(a,function(b){Z=b.instance.exports;za=Z.wd;Ha();O=Z.zd;Ja.unshift(Z.xd);La--;0==La&&(null!==Ma&&(clearInterval(Ma),Ma=null),Oa&&(b=Oa,Oa=null,b()))}).catch(ca);return{}}(),bc=a=>(bc=Z.yd)(a),pd=r._malloc=a=>(pd=r._malloc=Z.Ad)(a),cc=r._free=a=>(cc=r._free=Z.Bd)(a),Wd=(a,b)=>(Wd=Z.Cd)(a,b),
|
||||
Xd=a=>(Xd=Z.Dd)(a),Yd=()=>(Yd=Z.Ed)();r.dynCall_viji=(a,b,c,e,f)=>(r.dynCall_viji=Z.Fd)(a,b,c,e,f);r.dynCall_vijiii=(a,b,c,e,f,k,n)=>(r.dynCall_vijiii=Z.Gd)(a,b,c,e,f,k,n);r.dynCall_viiiiij=(a,b,c,e,f,k,n,l)=>(r.dynCall_viiiiij=Z.Hd)(a,b,c,e,f,k,n,l);r.dynCall_iiiji=(a,b,c,e,f,k)=>(r.dynCall_iiiji=Z.Id)(a,b,c,e,f,k);r.dynCall_jii=(a,b,c)=>(r.dynCall_jii=Z.Jd)(a,b,c);r.dynCall_vij=(a,b,c,e)=>(r.dynCall_vij=Z.Kd)(a,b,c,e);r.dynCall_jiiiiii=(a,b,c,e,f,k,n)=>(r.dynCall_jiiiiii=Z.Ld)(a,b,c,e,f,k,n);
|
||||
r.dynCall_jiiiiji=(a,b,c,e,f,k,n,l)=>(r.dynCall_jiiiiji=Z.Md)(a,b,c,e,f,k,n,l);r.dynCall_ji=(a,b)=>(r.dynCall_ji=Z.Nd)(a,b);r.dynCall_iijj=(a,b,c,e,f,k)=>(r.dynCall_iijj=Z.Od)(a,b,c,e,f,k);r.dynCall_iiji=(a,b,c,e,f)=>(r.dynCall_iiji=Z.Pd)(a,b,c,e,f);r.dynCall_iijjiii=(a,b,c,e,f,k,n,l,p)=>(r.dynCall_iijjiii=Z.Qd)(a,b,c,e,f,k,n,l,p);r.dynCall_iij=(a,b,c,e)=>(r.dynCall_iij=Z.Rd)(a,b,c,e);r.dynCall_vijjjii=(a,b,c,e,f,k,n,l,p,v)=>(r.dynCall_vijjjii=Z.Sd)(a,b,c,e,f,k,n,l,p,v);
|
||||
r.dynCall_jiji=(a,b,c,e,f)=>(r.dynCall_jiji=Z.Td)(a,b,c,e,f);r.dynCall_viijii=(a,b,c,e,f,k,n)=>(r.dynCall_viijii=Z.Ud)(a,b,c,e,f,k,n);r.dynCall_iiiiij=(a,b,c,e,f,k,n)=>(r.dynCall_iiiiij=Z.Vd)(a,b,c,e,f,k,n);r.dynCall_iiiiijj=(a,b,c,e,f,k,n,l,p)=>(r.dynCall_iiiiijj=Z.Wd)(a,b,c,e,f,k,n,l,p);r.dynCall_iiiiiijj=(a,b,c,e,f,k,n,l,p,v)=>(r.dynCall_iiiiiijj=Z.Xd)(a,b,c,e,f,k,n,l,p,v);function Rd(a,b,c,e,f){var k=Yd();try{O.get(a)(b,c,e,f)}catch(n){Xd(k);if(n!==n+0)throw n;Wd(1,0)}}
|
||||
function Id(a,b,c){var e=Yd();try{return O.get(a)(b,c)}catch(f){Xd(e);if(f!==f+0)throw f;Wd(1,0)}}function Pd(a,b,c){var e=Yd();try{O.get(a)(b,c)}catch(f){Xd(e);if(f!==f+0)throw f;Wd(1,0)}}function Hd(a,b){var c=Yd();try{return O.get(a)(b)}catch(e){Xd(c);if(e!==e+0)throw e;Wd(1,0)}}function Od(a,b){var c=Yd();try{O.get(a)(b)}catch(e){Xd(c);if(e!==e+0)throw e;Wd(1,0)}}function Jd(a,b,c,e){var f=Yd();try{return O.get(a)(b,c,e)}catch(k){Xd(f);if(k!==k+0)throw k;Wd(1,0)}}
|
||||
function Ud(a,b,c,e,f,k,n,l,p,v){var w=Yd();try{O.get(a)(b,c,e,f,k,n,l,p,v)}catch(A){Xd(w);if(A!==A+0)throw A;Wd(1,0)}}function Qd(a,b,c,e){var f=Yd();try{O.get(a)(b,c,e)}catch(k){Xd(f);if(k!==k+0)throw k;Wd(1,0)}}function Td(a,b,c,e,f,k,n){var l=Yd();try{O.get(a)(b,c,e,f,k,n)}catch(p){Xd(l);if(p!==p+0)throw p;Wd(1,0)}}function Md(a,b,c,e,f,k,n,l){var p=Yd();try{return O.get(a)(b,c,e,f,k,n,l)}catch(v){Xd(p);if(v!==v+0)throw v;Wd(1,0)}}
|
||||
function Sd(a,b,c,e,f,k){var n=Yd();try{O.get(a)(b,c,e,f,k)}catch(l){Xd(n);if(l!==l+0)throw l;Wd(1,0)}}function Kd(a,b,c,e,f){var k=Yd();try{return O.get(a)(b,c,e,f)}catch(n){Xd(k);if(n!==n+0)throw n;Wd(1,0)}}function Nd(a,b,c,e,f,k,n,l,p,v){var w=Yd();try{return O.get(a)(b,c,e,f,k,n,l,p,v)}catch(A){Xd(w);if(A!==A+0)throw A;Wd(1,0)}}function Ld(a,b,c,e,f,k,n){var l=Yd();try{return O.get(a)(b,c,e,f,k,n)}catch(p){Xd(l);if(p!==p+0)throw p;Wd(1,0)}}var Zd,$d;Oa=function ae(){Zd||be();Zd||(Oa=ae)};
|
||||
function be(){if(!(0<La)){if(!$d&&($d=1,Wa(Ia),0<La))return;Zd||(Zd=1,r.calledRun=1,Aa||(Wa(Ja),aa(r),r.onRuntimeInitialized?.(),Wa(Ka)))}}be();moduleRtn=da;
|
||||
|
||||
|
||||
return moduleRtn;
|
||||
}
|
||||
);
|
||||
})();
|
||||
export default CanvasKitInit;
|
||||
12084
internal/form_generator/templates/canvaskit/canvaskit.js.symbols
Normal file
BIN
internal/form_generator/templates/canvaskit/canvaskit.wasm
Normal file
@@ -0,0 +1,191 @@
|
||||
|
||||
var CanvasKitInit = (() => {
|
||||
var _scriptName = import.meta.url;
|
||||
|
||||
return (
|
||||
function(moduleArg = {}) {
|
||||
var moduleRtn;
|
||||
|
||||
var r=moduleArg,aa,ca,da=new Promise((a,b)=>{aa=a;ca=b}),ea="object"==typeof window,ha="function"==typeof importScripts;
|
||||
(function(a){a.Xd=a.Xd||[];a.Xd.push(function(){a.MakeSWCanvasSurface=function(b){var c=b,e="undefined"!==typeof OffscreenCanvas&&c instanceof OffscreenCanvas;if(!("undefined"!==typeof HTMLCanvasElement&&c instanceof HTMLCanvasElement||e||(c=document.getElementById(b),c)))throw"Canvas with id "+b+" was not found";if(b=a.MakeSurface(c.width,c.height))b.ue=c;return b};a.MakeCanvasSurface||(a.MakeCanvasSurface=a.MakeSWCanvasSurface);a.MakeSurface=function(b,c){var e={width:b,height:c,colorType:a.ColorType.RGBA_8888,
|
||||
alphaType:a.AlphaType.Unpremul,colorSpace:a.ColorSpace.SRGB},f=b*c*4,k=a._malloc(f);if(e=a.Surface._makeRasterDirect(e,k,4*b))e.ue=null,e.Ue=b,e.Re=c,e.Se=f,e.Be=k,e.getCanvas().clear(a.TRANSPARENT);return e};a.MakeRasterDirectSurface=function(b,c,e){return a.Surface._makeRasterDirect(b,c.byteOffset,e)};a.Surface.prototype.flush=function(b){a.Ud(this.Td);this._flush();if(this.ue){var c=new Uint8ClampedArray(a.HEAPU8.buffer,this.Be,this.Se);c=new ImageData(c,this.Ue,this.Re);b?this.ue.getContext("2d").putImageData(c,
|
||||
0,0,b[0],b[1],b[2]-b[0],b[3]-b[1]):this.ue.getContext("2d").putImageData(c,0,0)}};a.Surface.prototype.dispose=function(){this.Be&&a._free(this.Be);this.delete()};a.Ud=a.Ud||function(){};a.ve=a.ve||function(){return null}})})(r);
|
||||
(function(a){a.Xd=a.Xd||[];a.Xd.push(function(){function b(l,q,v){return l&&l.hasOwnProperty(q)?l[q]:v}function c(l){var q=ja(ka);ka[q]=l;return q}function e(l){return l.naturalHeight||l.videoHeight||l.displayHeight||l.height}function f(l){return l.naturalWidth||l.videoWidth||l.displayWidth||l.width}function k(l,q,v,w){l.bindTexture(l.TEXTURE_2D,q);w||v.alphaType!==a.AlphaType.Premul||l.pixelStorei(l.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0);return q}function n(l,q,v){v||q.alphaType!==a.AlphaType.Premul||
|
||||
l.pixelStorei(l.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);l.bindTexture(l.TEXTURE_2D,null)}a.GetWebGLContext=function(l,q){if(!l)throw"null canvas passed into makeWebGLContext";var v={alpha:b(q,"alpha",1),depth:b(q,"depth",1),stencil:b(q,"stencil",8),antialias:b(q,"antialias",0),premultipliedAlpha:b(q,"premultipliedAlpha",1),preserveDrawingBuffer:b(q,"preserveDrawingBuffer",0),preferLowPowerToHighPerformance:b(q,"preferLowPowerToHighPerformance",0),failIfMajorPerformanceCaveat:b(q,"failIfMajorPerformanceCaveat",
|
||||
0),enableExtensionsByDefault:b(q,"enableExtensionsByDefault",1),explicitSwapControl:b(q,"explicitSwapControl",0),renderViaOffscreenBackBuffer:b(q,"renderViaOffscreenBackBuffer",0)};v.majorVersion=q&&q.majorVersion?q.majorVersion:"undefined"!==typeof WebGL2RenderingContext?2:1;if(v.explicitSwapControl)throw"explicitSwapControl is not supported";l=la(l,v);if(!l)return 0;oa(l);A.fe.getExtension("WEBGL_debug_renderer_info");return l};a.deleteContext=function(l){A===pa[l]&&(A=null);"object"==typeof JSEvents&&
|
||||
JSEvents.uf(pa[l].fe.canvas);pa[l]&&pa[l].fe.canvas&&(pa[l].fe.canvas.Pe=void 0);pa[l]=null};a._setTextureCleanup({deleteTexture:function(l,q){var v=ka[q];v&&pa[l].fe.deleteTexture(v);ka[q]=null}});a.MakeWebGLContext=function(l){if(!this.Ud(l))return null;var q=this._MakeGrContext();if(!q)return null;q.Td=l;var v=q.delete.bind(q);q["delete"]=function(){a.Ud(this.Td);v()}.bind(q);return A.De=q};a.MakeGrContext=a.MakeWebGLContext;a.GrDirectContext.prototype.getResourceCacheLimitBytes=function(){a.Ud(this.Td);
|
||||
this._getResourceCacheLimitBytes()};a.GrDirectContext.prototype.getResourceCacheUsageBytes=function(){a.Ud(this.Td);this._getResourceCacheUsageBytes()};a.GrDirectContext.prototype.releaseResourcesAndAbandonContext=function(){a.Ud(this.Td);this._releaseResourcesAndAbandonContext()};a.GrDirectContext.prototype.setResourceCacheLimitBytes=function(l){a.Ud(this.Td);this._setResourceCacheLimitBytes(l)};a.MakeOnScreenGLSurface=function(l,q,v,w,z,D){if(!this.Ud(l.Td))return null;q=void 0===z||void 0===D?
|
||||
this._MakeOnScreenGLSurface(l,q,v,w):this._MakeOnScreenGLSurface(l,q,v,w,z,D);if(!q)return null;q.Td=l.Td;return q};a.MakeRenderTarget=function(){var l=arguments[0];if(!this.Ud(l.Td))return null;if(3===arguments.length){var q=this._MakeRenderTargetWH(l,arguments[1],arguments[2]);if(!q)return null}else if(2===arguments.length){if(q=this._MakeRenderTargetII(l,arguments[1]),!q)return null}else return null;q.Td=l.Td;return q};a.MakeWebGLCanvasSurface=function(l,q,v){q=q||null;var w=l,z="undefined"!==
|
||||
typeof OffscreenCanvas&&w instanceof OffscreenCanvas;if(!("undefined"!==typeof HTMLCanvasElement&&w instanceof HTMLCanvasElement||z||(w=document.getElementById(l),w)))throw"Canvas with id "+l+" was not found";l=this.GetWebGLContext(w,v);if(!l||0>l)throw"failed to create webgl context: err "+l;l=this.MakeWebGLContext(l);q=this.MakeOnScreenGLSurface(l,w.width,w.height,q);return q?q:(q=w.cloneNode(!0),w.parentNode.replaceChild(q,w),q.classList.add("ck-replaced"),a.MakeSWCanvasSurface(q))};a.MakeCanvasSurface=
|
||||
a.MakeWebGLCanvasSurface;a.Surface.prototype.makeImageFromTexture=function(l,q){a.Ud(this.Td);l=c(l);if(q=this._makeImageFromTexture(this.Td,l,q))q.oe=l;return q};a.Surface.prototype.makeImageFromTextureSource=function(l,q,v){q||={height:e(l),width:f(l),colorType:a.ColorType.RGBA_8888,alphaType:v?a.AlphaType.Premul:a.AlphaType.Unpremul};q.colorSpace||(q.colorSpace=a.ColorSpace.SRGB);a.Ud(this.Td);var w=A.fe;v=k(w,w.createTexture(),q,v);2===A.version?w.texImage2D(w.TEXTURE_2D,0,w.RGBA,q.width,q.height,
|
||||
0,w.RGBA,w.UNSIGNED_BYTE,l):w.texImage2D(w.TEXTURE_2D,0,w.RGBA,w.RGBA,w.UNSIGNED_BYTE,l);n(w,q);this._resetContext();return this.makeImageFromTexture(v,q)};a.Surface.prototype.updateTextureFromSource=function(l,q,v){if(l.oe){a.Ud(this.Td);var w=l.getImageInfo(),z=A.fe,D=k(z,ka[l.oe],w,v);2===A.version?z.texImage2D(z.TEXTURE_2D,0,z.RGBA,f(q),e(q),0,z.RGBA,z.UNSIGNED_BYTE,q):z.texImage2D(z.TEXTURE_2D,0,z.RGBA,z.RGBA,z.UNSIGNED_BYTE,q);n(z,w,v);this._resetContext();ka[l.oe]=null;l.oe=c(D);w.colorSpace=
|
||||
l.getColorSpace();q=this._makeImageFromTexture(this.Td,l.oe,w);v=l.Sd.Vd;z=l.Sd.Zd;l.Sd.Vd=q.Sd.Vd;l.Sd.Zd=q.Sd.Zd;q.Sd.Vd=v;q.Sd.Zd=z;q.delete();w.colorSpace.delete()}};a.MakeLazyImageFromTextureSource=function(l,q,v){q||={height:e(l),width:f(l),colorType:a.ColorType.RGBA_8888,alphaType:v?a.AlphaType.Premul:a.AlphaType.Unpremul};q.colorSpace||(q.colorSpace=a.ColorSpace.SRGB);var w={makeTexture:function(){var z=A,D=z.fe,I=k(D,D.createTexture(),q,v);2===z.version?D.texImage2D(D.TEXTURE_2D,0,D.RGBA,
|
||||
q.width,q.height,0,D.RGBA,D.UNSIGNED_BYTE,l):D.texImage2D(D.TEXTURE_2D,0,D.RGBA,D.RGBA,D.UNSIGNED_BYTE,l);n(D,q,v);return c(I)},freeSrc:function(){}};"VideoFrame"===l.constructor.name&&(w.freeSrc=function(){l.close()});return a.Image._makeFromGenerator(q,w)};a.Ud=function(l){return l?oa(l):!1};a.ve=function(){return A&&A.De&&!A.De.isDeleted()?A.De:null}})})(r);
|
||||
(function(a){function b(g){return(f(255*g[3])<<24|f(255*g[0])<<16|f(255*g[1])<<8|f(255*g[2])<<0)>>>0}function c(g){if(g&&g._ck)return g;if(g instanceof Float32Array){for(var d=Math.floor(g.length/4),h=new Uint32Array(d),m=0;m<d;m++)h[m]=b(g.slice(4*m,4*(m+1)));return h}if(g instanceof Uint32Array)return g;if(g instanceof Array&&g[0]instanceof Float32Array)return g.map(b)}function e(g){if(void 0===g)return 1;var d=parseFloat(g);return g&&-1!==g.indexOf("%")?d/100:d}function f(g){return Math.round(Math.max(0,
|
||||
Math.min(g||0,255)))}function k(g,d){d&&d._ck||a._free(g)}function n(g,d,h){if(!g||!g.length)return K;if(g&&g._ck)return g.byteOffset;var m=a[d].BYTES_PER_ELEMENT;h||=a._malloc(g.length*m);a[d].set(g,h/m);return h}function l(g){var d={be:K,count:g.length,colorType:a.ColorType.RGBA_F32};if(g instanceof Float32Array)d.be=n(g,"HEAPF32"),d.count=g.length/4;else if(g instanceof Uint32Array)d.be=n(g,"HEAPU32"),d.colorType=a.ColorType.RGBA_8888;else if(g instanceof Array){if(g&&g.length){for(var h=a._malloc(16*
|
||||
g.length),m=0,t=h/4,u=0;u<g.length;u++)for(var x=0;4>x;x++)a.HEAPF32[t+m]=g[u][x],m++;g=h}else g=K;d.be=g}else throw"Invalid argument to copyFlexibleColorArray, Not a color array "+typeof g;return d}function q(g){if(!g)return K;var d=ba.toTypedArray();if(g.length){if(6===g.length||9===g.length)return n(g,"HEAPF32",P),6===g.length&&a.HEAPF32.set(Wc,6+P/4),P;if(16===g.length)return d[0]=g[0],d[1]=g[1],d[2]=g[3],d[3]=g[4],d[4]=g[5],d[5]=g[7],d[6]=g[12],d[7]=g[13],d[8]=g[15],P;throw"invalid matrix size";
|
||||
}if(void 0===g.m11)throw"invalid matrix argument";d[0]=g.m11;d[1]=g.m21;d[2]=g.m41;d[3]=g.m12;d[4]=g.m22;d[5]=g.m42;d[6]=g.m14;d[7]=g.m24;d[8]=g.m44;return P}function v(g){if(!g)return K;var d=Y.toTypedArray();if(g.length){if(16!==g.length&&6!==g.length&&9!==g.length)throw"invalid matrix size";if(16===g.length)return n(g,"HEAPF32",ma);d.fill(0);d[0]=g[0];d[1]=g[1];d[3]=g[2];d[4]=g[3];d[5]=g[4];d[7]=g[5];d[10]=1;d[12]=g[6];d[13]=g[7];d[15]=g[8];6===g.length&&(d[12]=0,d[13]=0,d[15]=1);return ma}if(void 0===
|
||||
g.m11)throw"invalid matrix argument";d[0]=g.m11;d[1]=g.m21;d[2]=g.m31;d[3]=g.m41;d[4]=g.m12;d[5]=g.m22;d[6]=g.m32;d[7]=g.m42;d[8]=g.m13;d[9]=g.m23;d[10]=g.m33;d[11]=g.m43;d[12]=g.m14;d[13]=g.m24;d[14]=g.m34;d[15]=g.m44;return ma}function w(g,d){return n(g,"HEAPF32",d||ia)}function z(g,d,h,m){var t=Ea.toTypedArray();t[0]=g;t[1]=d;t[2]=h;t[3]=m;return ia}function D(g){for(var d=new Float32Array(4),h=0;4>h;h++)d[h]=a.HEAPF32[g/4+h];return d}function I(g,d){return n(g,"HEAPF32",d||W)}function Q(g,d){return n(g,
|
||||
"HEAPF32",d||ub)}a.Color=function(g,d,h,m){void 0===m&&(m=1);return a.Color4f(f(g)/255,f(d)/255,f(h)/255,m)};a.ColorAsInt=function(g,d,h,m){void 0===m&&(m=255);return(f(m)<<24|f(g)<<16|f(d)<<8|f(h)<<0&268435455)>>>0};a.Color4f=function(g,d,h,m){void 0===m&&(m=1);return Float32Array.of(g,d,h,m)};Object.defineProperty(a,"TRANSPARENT",{get:function(){return a.Color4f(0,0,0,0)}});Object.defineProperty(a,"BLACK",{get:function(){return a.Color4f(0,0,0,1)}});Object.defineProperty(a,"WHITE",{get:function(){return a.Color4f(1,
|
||||
1,1,1)}});Object.defineProperty(a,"RED",{get:function(){return a.Color4f(1,0,0,1)}});Object.defineProperty(a,"GREEN",{get:function(){return a.Color4f(0,1,0,1)}});Object.defineProperty(a,"BLUE",{get:function(){return a.Color4f(0,0,1,1)}});Object.defineProperty(a,"YELLOW",{get:function(){return a.Color4f(1,1,0,1)}});Object.defineProperty(a,"CYAN",{get:function(){return a.Color4f(0,1,1,1)}});Object.defineProperty(a,"MAGENTA",{get:function(){return a.Color4f(1,0,1,1)}});a.getColorComponents=function(g){return[Math.floor(255*
|
||||
g[0]),Math.floor(255*g[1]),Math.floor(255*g[2]),g[3]]};a.parseColorString=function(g,d){g=g.toLowerCase();if(g.startsWith("#")){d=255;switch(g.length){case 9:d=parseInt(g.slice(7,9),16);case 7:var h=parseInt(g.slice(1,3),16);var m=parseInt(g.slice(3,5),16);var t=parseInt(g.slice(5,7),16);break;case 5:d=17*parseInt(g.slice(4,5),16);case 4:h=17*parseInt(g.slice(1,2),16),m=17*parseInt(g.slice(2,3),16),t=17*parseInt(g.slice(3,4),16)}return a.Color(h,m,t,d/255)}return g.startsWith("rgba")?(g=g.slice(5,
|
||||
-1),g=g.split(","),a.Color(+g[0],+g[1],+g[2],e(g[3]))):g.startsWith("rgb")?(g=g.slice(4,-1),g=g.split(","),a.Color(+g[0],+g[1],+g[2],e(g[3]))):g.startsWith("gray(")||g.startsWith("hsl")||!d||(g=d[g],void 0===g)?a.BLACK:g};a.multiplyByAlpha=function(g,d){g=g.slice();g[3]=Math.max(0,Math.min(g[3]*d,1));return g};a.Malloc=function(g,d){var h=a._malloc(d*g.BYTES_PER_ELEMENT);return{_ck:!0,length:d,byteOffset:h,ke:null,subarray:function(m,t){m=this.toTypedArray().subarray(m,t);m._ck=!0;return m},toTypedArray:function(){if(this.ke&&
|
||||
this.ke.length)return this.ke;this.ke=new g(a.HEAPU8.buffer,h,d);this.ke._ck=!0;return this.ke}}};a.Free=function(g){a._free(g.byteOffset);g.byteOffset=K;g.toTypedArray=null;g.ke=null};var P=K,ba,ma=K,Y,ia=K,Ea,fa,W=K,Ub,Ba=K,Vb,vb=K,Wb,wb=K,$a,Na=K,Xb,ub=K,Yb,Zb=K,Wc=Float32Array.of(0,0,1),K=0;a.onRuntimeInitialized=function(){function g(d,h,m,t,u,x,C){x||(x=4*t.width,t.colorType===a.ColorType.RGBA_F16?x*=2:t.colorType===a.ColorType.RGBA_F32&&(x*=4));var G=x*t.height;var F=u?u.byteOffset:a._malloc(G);
|
||||
if(C?!d._readPixels(t,F,x,h,m,C):!d._readPixels(t,F,x,h,m))return u||a._free(F),null;if(u)return u.toTypedArray();switch(t.colorType){case a.ColorType.RGBA_8888:case a.ColorType.RGBA_F16:d=(new Uint8Array(a.HEAPU8.buffer,F,G)).slice();break;case a.ColorType.RGBA_F32:d=(new Float32Array(a.HEAPU8.buffer,F,G)).slice();break;default:return null}a._free(F);return d}Ea=a.Malloc(Float32Array,4);ia=Ea.byteOffset;Y=a.Malloc(Float32Array,16);ma=Y.byteOffset;ba=a.Malloc(Float32Array,9);P=ba.byteOffset;Xb=a.Malloc(Float32Array,
|
||||
12);ub=Xb.byteOffset;Yb=a.Malloc(Float32Array,12);Zb=Yb.byteOffset;fa=a.Malloc(Float32Array,4);W=fa.byteOffset;Ub=a.Malloc(Float32Array,4);Ba=Ub.byteOffset;Vb=a.Malloc(Float32Array,3);vb=Vb.byteOffset;Wb=a.Malloc(Float32Array,3);wb=Wb.byteOffset;$a=a.Malloc(Int32Array,4);Na=$a.byteOffset;a.ColorSpace.SRGB=a.ColorSpace._MakeSRGB();a.ColorSpace.DISPLAY_P3=a.ColorSpace._MakeDisplayP3();a.ColorSpace.ADOBE_RGB=a.ColorSpace._MakeAdobeRGB();a.GlyphRunFlags={IsWhiteSpace:a._GlyphRunFlags_isWhiteSpace};a.Path.MakeFromCmds=
|
||||
function(d){var h=n(d,"HEAPF32"),m=a.Path._MakeFromCmds(h,d.length);k(h,d);return m};a.Path.MakeFromVerbsPointsWeights=function(d,h,m){var t=n(d,"HEAPU8"),u=n(h,"HEAPF32"),x=n(m,"HEAPF32"),C=a.Path._MakeFromVerbsPointsWeights(t,d.length,u,h.length,x,m&&m.length||0);k(t,d);k(u,h);k(x,m);return C};a.Path.prototype.addArc=function(d,h,m){d=I(d);this._addArc(d,h,m);return this};a.Path.prototype.addCircle=function(d,h,m,t){this._addCircle(d,h,m,!!t);return this};a.Path.prototype.addOval=function(d,h,m){void 0===
|
||||
m&&(m=1);d=I(d);this._addOval(d,!!h,m);return this};a.Path.prototype.addPath=function(){var d=Array.prototype.slice.call(arguments),h=d[0],m=!1;"boolean"===typeof d[d.length-1]&&(m=d.pop());if(1===d.length)this._addPath(h,1,0,0,0,1,0,0,0,1,m);else if(2===d.length)d=d[1],this._addPath(h,d[0],d[1],d[2],d[3],d[4],d[5],d[6]||0,d[7]||0,d[8]||1,m);else if(7===d.length||10===d.length)this._addPath(h,d[1],d[2],d[3],d[4],d[5],d[6],d[7]||0,d[8]||0,d[9]||1,m);else return null;return this};a.Path.prototype.addPoly=
|
||||
function(d,h){var m=n(d,"HEAPF32");this._addPoly(m,d.length/2,h);k(m,d);return this};a.Path.prototype.addRect=function(d,h){d=I(d);this._addRect(d,!!h);return this};a.Path.prototype.addRRect=function(d,h){d=Q(d);this._addRRect(d,!!h);return this};a.Path.prototype.addVerbsPointsWeights=function(d,h,m){var t=n(d,"HEAPU8"),u=n(h,"HEAPF32"),x=n(m,"HEAPF32");this._addVerbsPointsWeights(t,d.length,u,h.length,x,m&&m.length||0);k(t,d);k(u,h);k(x,m)};a.Path.prototype.arc=function(d,h,m,t,u,x){d=a.LTRBRect(d-
|
||||
m,h-m,d+m,h+m);u=(u-t)/Math.PI*180-360*!!x;x=new a.Path;x.addArc(d,t/Math.PI*180,u);this.addPath(x,!0);x.delete();return this};a.Path.prototype.arcToOval=function(d,h,m,t){d=I(d);this._arcToOval(d,h,m,t);return this};a.Path.prototype.arcToRotated=function(d,h,m,t,u,x,C){this._arcToRotated(d,h,m,!!t,!!u,x,C);return this};a.Path.prototype.arcToTangent=function(d,h,m,t,u){this._arcToTangent(d,h,m,t,u);return this};a.Path.prototype.close=function(){this._close();return this};a.Path.prototype.conicTo=
|
||||
function(d,h,m,t,u){this._conicTo(d,h,m,t,u);return this};a.Path.prototype.computeTightBounds=function(d){this._computeTightBounds(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.Path.prototype.cubicTo=function(d,h,m,t,u,x){this._cubicTo(d,h,m,t,u,x);return this};a.Path.prototype.dash=function(d,h,m){return this._dash(d,h,m)?this:null};a.Path.prototype.getBounds=function(d){this._getBounds(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.Path.prototype.lineTo=function(d,
|
||||
h){this._lineTo(d,h);return this};a.Path.prototype.moveTo=function(d,h){this._moveTo(d,h);return this};a.Path.prototype.offset=function(d,h){this._transform(1,0,d,0,1,h,0,0,1);return this};a.Path.prototype.quadTo=function(d,h,m,t){this._quadTo(d,h,m,t);return this};a.Path.prototype.rArcTo=function(d,h,m,t,u,x,C){this._rArcTo(d,h,m,t,u,x,C);return this};a.Path.prototype.rConicTo=function(d,h,m,t,u){this._rConicTo(d,h,m,t,u);return this};a.Path.prototype.rCubicTo=function(d,h,m,t,u,x){this._rCubicTo(d,
|
||||
h,m,t,u,x);return this};a.Path.prototype.rLineTo=function(d,h){this._rLineTo(d,h);return this};a.Path.prototype.rMoveTo=function(d,h){this._rMoveTo(d,h);return this};a.Path.prototype.rQuadTo=function(d,h,m,t){this._rQuadTo(d,h,m,t);return this};a.Path.prototype.stroke=function(d){d=d||{};d.width=d.width||1;d.miter_limit=d.miter_limit||4;d.cap=d.cap||a.StrokeCap.Butt;d.join=d.join||a.StrokeJoin.Miter;d.precision=d.precision||1;return this._stroke(d)?this:null};a.Path.prototype.transform=function(){if(1===
|
||||
arguments.length){var d=arguments[0];this._transform(d[0],d[1],d[2],d[3],d[4],d[5],d[6]||0,d[7]||0,d[8]||1)}else if(6===arguments.length||9===arguments.length)d=arguments,this._transform(d[0],d[1],d[2],d[3],d[4],d[5],d[6]||0,d[7]||0,d[8]||1);else throw"transform expected to take 1 or 9 arguments. Got "+arguments.length;return this};a.Path.prototype.trim=function(d,h,m){return this._trim(d,h,!!m)?this:null};a.Image.prototype.encodeToBytes=function(d,h){var m=a.ve();d=d||a.ImageFormat.PNG;h=h||100;
|
||||
return m?this._encodeToBytes(d,h,m):this._encodeToBytes(d,h)};a.Image.prototype.makeShaderCubic=function(d,h,m,t,u){u=q(u);return this._makeShaderCubic(d,h,m,t,u)};a.Image.prototype.makeShaderOptions=function(d,h,m,t,u){u=q(u);return this._makeShaderOptions(d,h,m,t,u)};a.Image.prototype.readPixels=function(d,h,m,t,u){var x=a.ve();return g(this,d,h,m,t,u,x)};a.Canvas.prototype.clear=function(d){a.Ud(this.Td);d=w(d);this._clear(d)};a.Canvas.prototype.clipRRect=function(d,h,m){a.Ud(this.Td);d=Q(d);this._clipRRect(d,
|
||||
h,m)};a.Canvas.prototype.clipRect=function(d,h,m){a.Ud(this.Td);d=I(d);this._clipRect(d,h,m)};a.Canvas.prototype.concat=function(d){a.Ud(this.Td);d=v(d);this._concat(d)};a.Canvas.prototype.drawArc=function(d,h,m,t,u){a.Ud(this.Td);d=I(d);this._drawArc(d,h,m,t,u)};a.Canvas.prototype.drawAtlas=function(d,h,m,t,u,x,C){if(d&&t&&h&&m&&h.length===m.length){a.Ud(this.Td);u||(u=a.BlendMode.SrcOver);var G=n(h,"HEAPF32"),F=n(m,"HEAPF32"),T=m.length/4,U=n(c(x),"HEAPU32");if(C&&"B"in C&&"C"in C)this._drawAtlasCubic(d,
|
||||
F,G,U,T,u,C.B,C.C,t);else{let p=a.FilterMode.Linear,y=a.MipmapMode.None;C&&(p=C.filter,"mipmap"in C&&(y=C.mipmap));this._drawAtlasOptions(d,F,G,U,T,u,p,y,t)}k(G,h);k(F,m);k(U,x)}};a.Canvas.prototype.drawCircle=function(d,h,m,t){a.Ud(this.Td);this._drawCircle(d,h,m,t)};a.Canvas.prototype.drawColor=function(d,h){a.Ud(this.Td);d=w(d);void 0!==h?this._drawColor(d,h):this._drawColor(d)};a.Canvas.prototype.drawColorInt=function(d,h){a.Ud(this.Td);this._drawColorInt(d,h||a.BlendMode.SrcOver)};a.Canvas.prototype.drawColorComponents=
|
||||
function(d,h,m,t,u){a.Ud(this.Td);d=z(d,h,m,t);void 0!==u?this._drawColor(d,u):this._drawColor(d)};a.Canvas.prototype.drawDRRect=function(d,h,m){a.Ud(this.Td);d=Q(d,ub);h=Q(h,Zb);this._drawDRRect(d,h,m)};a.Canvas.prototype.drawImage=function(d,h,m,t){a.Ud(this.Td);this._drawImage(d,h,m,t||null)};a.Canvas.prototype.drawImageCubic=function(d,h,m,t,u,x){a.Ud(this.Td);this._drawImageCubic(d,h,m,t,u,x||null)};a.Canvas.prototype.drawImageOptions=function(d,h,m,t,u,x){a.Ud(this.Td);this._drawImageOptions(d,
|
||||
h,m,t,u,x||null)};a.Canvas.prototype.drawImageNine=function(d,h,m,t,u){a.Ud(this.Td);h=n(h,"HEAP32",Na);m=I(m);this._drawImageNine(d,h,m,t,u||null)};a.Canvas.prototype.drawImageRect=function(d,h,m,t,u){a.Ud(this.Td);I(h,W);I(m,Ba);this._drawImageRect(d,W,Ba,t,!!u)};a.Canvas.prototype.drawImageRectCubic=function(d,h,m,t,u,x){a.Ud(this.Td);I(h,W);I(m,Ba);this._drawImageRectCubic(d,W,Ba,t,u,x||null)};a.Canvas.prototype.drawImageRectOptions=function(d,h,m,t,u,x){a.Ud(this.Td);I(h,W);I(m,Ba);this._drawImageRectOptions(d,
|
||||
W,Ba,t,u,x||null)};a.Canvas.prototype.drawLine=function(d,h,m,t,u){a.Ud(this.Td);this._drawLine(d,h,m,t,u)};a.Canvas.prototype.drawOval=function(d,h){a.Ud(this.Td);d=I(d);this._drawOval(d,h)};a.Canvas.prototype.drawPaint=function(d){a.Ud(this.Td);this._drawPaint(d)};a.Canvas.prototype.drawParagraph=function(d,h,m){a.Ud(this.Td);this._drawParagraph(d,h,m)};a.Canvas.prototype.drawPatch=function(d,h,m,t,u){if(24>d.length)throw"Need 12 cubic points";if(h&&4>h.length)throw"Need 4 colors";if(m&&8>m.length)throw"Need 4 shader coordinates";
|
||||
a.Ud(this.Td);const x=n(d,"HEAPF32"),C=h?n(c(h),"HEAPU32"):K,G=m?n(m,"HEAPF32"):K;t||(t=a.BlendMode.Modulate);this._drawPatch(x,C,G,t,u);k(G,m);k(C,h);k(x,d)};a.Canvas.prototype.drawPath=function(d,h){a.Ud(this.Td);this._drawPath(d,h)};a.Canvas.prototype.drawPicture=function(d){a.Ud(this.Td);this._drawPicture(d)};a.Canvas.prototype.drawPoints=function(d,h,m){a.Ud(this.Td);var t=n(h,"HEAPF32");this._drawPoints(d,t,h.length/2,m);k(t,h)};a.Canvas.prototype.drawRRect=function(d,h){a.Ud(this.Td);d=Q(d);
|
||||
this._drawRRect(d,h)};a.Canvas.prototype.drawRect=function(d,h){a.Ud(this.Td);d=I(d);this._drawRect(d,h)};a.Canvas.prototype.drawRect4f=function(d,h,m,t,u){a.Ud(this.Td);this._drawRect4f(d,h,m,t,u)};a.Canvas.prototype.drawShadow=function(d,h,m,t,u,x,C){a.Ud(this.Td);var G=n(u,"HEAPF32"),F=n(x,"HEAPF32");h=n(h,"HEAPF32",vb);m=n(m,"HEAPF32",wb);this._drawShadow(d,h,m,t,G,F,C);k(G,u);k(F,x)};a.getShadowLocalBounds=function(d,h,m,t,u,x,C){d=q(d);m=n(m,"HEAPF32",vb);t=n(t,"HEAPF32",wb);if(!this._getShadowLocalBounds(d,
|
||||
h,m,t,u,x,W))return null;h=fa.toTypedArray();return C?(C.set(h),C):h.slice()};a.Canvas.prototype.drawTextBlob=function(d,h,m,t){a.Ud(this.Td);this._drawTextBlob(d,h,m,t)};a.Canvas.prototype.drawVertices=function(d,h,m){a.Ud(this.Td);this._drawVertices(d,h,m)};a.Canvas.prototype.getDeviceClipBounds=function(d){this._getDeviceClipBounds(Na);var h=$a.toTypedArray();d?d.set(h):d=h.slice();return d};a.Canvas.prototype.quickReject=function(d){d=I(d);return this._quickReject(d)};a.Canvas.prototype.getLocalToDevice=
|
||||
function(){this._getLocalToDevice(ma);for(var d=ma,h=Array(16),m=0;16>m;m++)h[m]=a.HEAPF32[d/4+m];return h};a.Canvas.prototype.getTotalMatrix=function(){this._getTotalMatrix(P);for(var d=Array(9),h=0;9>h;h++)d[h]=a.HEAPF32[P/4+h];return d};a.Canvas.prototype.makeSurface=function(d){d=this._makeSurface(d);d.Td=this.Td;return d};a.Canvas.prototype.readPixels=function(d,h,m,t,u){a.Ud(this.Td);return g(this,d,h,m,t,u)};a.Canvas.prototype.saveLayer=function(d,h,m,t,u){h=I(h);return this._saveLayer(d||
|
||||
null,h,m||null,t||0,u||a.TileMode.Clamp)};a.Canvas.prototype.writePixels=function(d,h,m,t,u,x,C,G){if(d.byteLength%(h*m))throw"pixels length must be a multiple of the srcWidth * srcHeight";a.Ud(this.Td);var F=d.byteLength/(h*m);x=x||a.AlphaType.Unpremul;C=C||a.ColorType.RGBA_8888;G=G||a.ColorSpace.SRGB;var T=F*h;F=n(d,"HEAPU8");h=this._writePixels({width:h,height:m,colorType:C,alphaType:x,colorSpace:G},F,T,t,u);k(F,d);return h};a.ColorFilter.MakeBlend=function(d,h,m){d=w(d);m=m||a.ColorSpace.SRGB;
|
||||
return a.ColorFilter._MakeBlend(d,h,m)};a.ColorFilter.MakeMatrix=function(d){if(!d||20!==d.length)throw"invalid color matrix";var h=n(d,"HEAPF32"),m=a.ColorFilter._makeMatrix(h);k(h,d);return m};a.ContourMeasure.prototype.getPosTan=function(d,h){this._getPosTan(d,W);d=fa.toTypedArray();return h?(h.set(d),h):d.slice()};a.ImageFilter.prototype.getOutputBounds=function(d,h,m){d=I(d,W);h=q(h);this._getOutputBounds(d,h,Na);h=$a.toTypedArray();return m?(m.set(h),m):h.slice()};a.ImageFilter.MakeDropShadow=
|
||||
function(d,h,m,t,u,x){u=w(u,ia);return a.ImageFilter._MakeDropShadow(d,h,m,t,u,x)};a.ImageFilter.MakeDropShadowOnly=function(d,h,m,t,u,x){u=w(u,ia);return a.ImageFilter._MakeDropShadowOnly(d,h,m,t,u,x)};a.ImageFilter.MakeImage=function(d,h,m,t){m=I(m,W);t=I(t,Ba);if("B"in h&&"C"in h)return a.ImageFilter._MakeImageCubic(d,h.B,h.C,m,t);const u=h.filter;let x=a.MipmapMode.None;"mipmap"in h&&(x=h.mipmap);return a.ImageFilter._MakeImageOptions(d,u,x,m,t)};a.ImageFilter.MakeMatrixTransform=function(d,h,
|
||||
m){d=q(d);if("B"in h&&"C"in h)return a.ImageFilter._MakeMatrixTransformCubic(d,h.B,h.C,m);const t=h.filter;let u=a.MipmapMode.None;"mipmap"in h&&(u=h.mipmap);return a.ImageFilter._MakeMatrixTransformOptions(d,t,u,m)};a.Paint.prototype.getColor=function(){this._getColor(ia);return D(ia)};a.Paint.prototype.setColor=function(d,h){h=h||null;d=w(d);this._setColor(d,h)};a.Paint.prototype.setColorComponents=function(d,h,m,t,u){u=u||null;d=z(d,h,m,t);this._setColor(d,u)};a.Path.prototype.getPoint=function(d,
|
||||
h){this._getPoint(d,W);d=fa.toTypedArray();return h?(h[0]=d[0],h[1]=d[1],h):d.slice(0,2)};a.Picture.prototype.makeShader=function(d,h,m,t,u){t=q(t);u=I(u);return this._makeShader(d,h,m,t,u)};a.Picture.prototype.cullRect=function(d){this._cullRect(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.PictureRecorder.prototype.beginRecording=function(d,h){d=I(d);return this._beginRecording(d,!!h)};a.Surface.prototype.getCanvas=function(){var d=this._getCanvas();d.Td=this.Td;return d};a.Surface.prototype.makeImageSnapshot=
|
||||
function(d){a.Ud(this.Td);d=n(d,"HEAP32",Na);return this._makeImageSnapshot(d)};a.Surface.prototype.makeSurface=function(d){a.Ud(this.Td);d=this._makeSurface(d);d.Td=this.Td;return d};a.Surface.prototype.Te=function(d,h){this.ne||(this.ne=this.getCanvas());return requestAnimationFrame(function(){a.Ud(this.Td);d(this.ne);this.flush(h)}.bind(this))};a.Surface.prototype.requestAnimationFrame||(a.Surface.prototype.requestAnimationFrame=a.Surface.prototype.Te);a.Surface.prototype.Qe=function(d,h){this.ne||
|
||||
(this.ne=this.getCanvas());requestAnimationFrame(function(){a.Ud(this.Td);d(this.ne);this.flush(h);this.dispose()}.bind(this))};a.Surface.prototype.drawOnce||(a.Surface.prototype.drawOnce=a.Surface.prototype.Qe);a.PathEffect.MakeDash=function(d,h){h||=0;if(!d.length||1===d.length%2)throw"Intervals array must have even length";var m=n(d,"HEAPF32");h=a.PathEffect._MakeDash(m,d.length,h);k(m,d);return h};a.PathEffect.MakeLine2D=function(d,h){h=q(h);return a.PathEffect._MakeLine2D(d,h)};a.PathEffect.MakePath2D=
|
||||
function(d,h){d=q(d);return a.PathEffect._MakePath2D(d,h)};a.Shader.MakeColor=function(d,h){h=h||null;d=w(d);return a.Shader._MakeColor(d,h)};a.Shader.Blend=a.Shader.MakeBlend;a.Shader.Color=a.Shader.MakeColor;a.Shader.MakeLinearGradient=function(d,h,m,t,u,x,C,G){G=G||null;var F=l(m),T=n(t,"HEAPF32");C=C||0;x=q(x);var U=fa.toTypedArray();U.set(d);U.set(h,2);d=a.Shader._MakeLinearGradient(W,F.be,F.colorType,T,F.count,u,C,x,G);k(F.be,m);t&&k(T,t);return d};a.Shader.MakeRadialGradient=function(d,h,m,
|
||||
t,u,x,C,G){G=G||null;var F=l(m),T=n(t,"HEAPF32");C=C||0;x=q(x);d=a.Shader._MakeRadialGradient(d[0],d[1],h,F.be,F.colorType,T,F.count,u,C,x,G);k(F.be,m);t&&k(T,t);return d};a.Shader.MakeSweepGradient=function(d,h,m,t,u,x,C,G,F,T){T=T||null;var U=l(m),p=n(t,"HEAPF32");C=C||0;G=G||0;F=F||360;x=q(x);d=a.Shader._MakeSweepGradient(d,h,U.be,U.colorType,p,U.count,u,G,F,C,x,T);k(U.be,m);t&&k(p,t);return d};a.Shader.MakeTwoPointConicalGradient=function(d,h,m,t,u,x,C,G,F,T){T=T||null;var U=l(u),p=n(x,"HEAPF32");
|
||||
F=F||0;G=q(G);var y=fa.toTypedArray();y.set(d);y.set(m,2);d=a.Shader._MakeTwoPointConicalGradient(W,h,t,U.be,U.colorType,p,U.count,C,F,G,T);k(U.be,u);x&&k(p,x);return d};a.Vertices.prototype.bounds=function(d){this._bounds(W);var h=fa.toTypedArray();return d?(d.set(h),d):h.slice()};a.Xd&&a.Xd.forEach(function(d){d()})};a.computeTonalColors=function(g){var d=n(g.ambient,"HEAPF32"),h=n(g.spot,"HEAPF32");this._computeTonalColors(d,h);var m={ambient:D(d),spot:D(h)};k(d,g.ambient);k(h,g.spot);return m};
|
||||
a.LTRBRect=function(g,d,h,m){return Float32Array.of(g,d,h,m)};a.XYWHRect=function(g,d,h,m){return Float32Array.of(g,d,g+h,d+m)};a.LTRBiRect=function(g,d,h,m){return Int32Array.of(g,d,h,m)};a.XYWHiRect=function(g,d,h,m){return Int32Array.of(g,d,g+h,d+m)};a.RRectXY=function(g,d,h){return Float32Array.of(g[0],g[1],g[2],g[3],d,h,d,h,d,h,d,h)};a.MakeAnimatedImageFromEncoded=function(g){g=new Uint8Array(g);var d=a._malloc(g.byteLength);a.HEAPU8.set(g,d);return(g=a._decodeAnimatedImage(d,g.byteLength))?
|
||||
g:null};a.MakeImageFromEncoded=function(g){g=new Uint8Array(g);var d=a._malloc(g.byteLength);a.HEAPU8.set(g,d);return(g=a._decodeImage(d,g.byteLength))?g:null};var ab=null;a.MakeImageFromCanvasImageSource=function(g){var d=g.width,h=g.height;ab||=document.createElement("canvas");ab.width=d;ab.height=h;var m=ab.getContext("2d",{willReadFrequently:!0});m.drawImage(g,0,0);g=m.getImageData(0,0,d,h);return a.MakeImage({width:d,height:h,alphaType:a.AlphaType.Unpremul,colorType:a.ColorType.RGBA_8888,colorSpace:a.ColorSpace.SRGB},
|
||||
g.data,4*d)};a.MakeImage=function(g,d,h){var m=a._malloc(d.length);a.HEAPU8.set(d,m);return a._MakeImage(g,m,d.length,h)};a.MakeVertices=function(g,d,h,m,t,u){var x=t&&t.length||0,C=0;h&&h.length&&(C|=1);m&&m.length&&(C|=2);void 0===u||u||(C|=4);g=new a._VerticesBuilder(g,d.length/2,x,C);n(d,"HEAPF32",g.positions());g.texCoords()&&n(h,"HEAPF32",g.texCoords());g.colors()&&n(c(m),"HEAPU32",g.colors());g.indices()&&n(t,"HEAPU16",g.indices());return g.detach()};(function(g){g.Xd=g.Xd||[];g.Xd.push(function(){function d(p){p&&
|
||||
(p.dir=0===p.dir?g.TextDirection.RTL:g.TextDirection.LTR);return p}function h(p){if(!p||!p.length)return[];for(var y=[],N=0;N<p.length;N+=5){var X=g.LTRBRect(p[N],p[N+1],p[N+2],p[N+3]),xa=g.TextDirection.LTR;0===p[N+4]&&(xa=g.TextDirection.RTL);y.push({rect:X,dir:xa})}g._free(p.byteOffset);return y}function m(p){p=p||{};void 0===p.weight&&(p.weight=g.FontWeight.Normal);p.width=p.width||g.FontWidth.Normal;p.slant=p.slant||g.FontSlant.Upright;return p}function t(p){if(!p||!p.length)return K;for(var y=
|
||||
[],N=0;N<p.length;N++){var X=u(p[N]);y.push(X)}return n(y,"HEAPU32")}function u(p){if(G[p])return G[p];var y=qa(p)+1,N=g._malloc(y);ra(p,N,y);return G[p]=N}function x(p){p._colorPtr=w(p.color);p._foregroundColorPtr=K;p._backgroundColorPtr=K;p._decorationColorPtr=K;p.foregroundColor&&(p._foregroundColorPtr=w(p.foregroundColor,F));p.backgroundColor&&(p._backgroundColorPtr=w(p.backgroundColor,T));p.decorationColor&&(p._decorationColorPtr=w(p.decorationColor,U));Array.isArray(p.fontFamilies)&&p.fontFamilies.length?
|
||||
(p._fontFamiliesPtr=t(p.fontFamilies),p._fontFamiliesLen=p.fontFamilies.length):(p._fontFamiliesPtr=K,p._fontFamiliesLen=0);if(p.locale){var y=p.locale;p._localePtr=u(y);p._localeLen=qa(y)}else p._localePtr=K,p._localeLen=0;if(Array.isArray(p.shadows)&&p.shadows.length){y=p.shadows;var N=y.map(function(na){return na.color||g.BLACK}),X=y.map(function(na){return na.blurRadius||0});p._shadowLen=y.length;for(var xa=g._malloc(8*y.length),xb=xa/4,yb=0;yb<y.length;yb++){var $b=y[yb].offset||[0,0];g.HEAPF32[xb]=
|
||||
$b[0];g.HEAPF32[xb+1]=$b[1];xb+=2}p._shadowColorsPtr=l(N).be;p._shadowOffsetsPtr=xa;p._shadowBlurRadiiPtr=n(X,"HEAPF32")}else p._shadowLen=0,p._shadowColorsPtr=K,p._shadowOffsetsPtr=K,p._shadowBlurRadiiPtr=K;Array.isArray(p.fontFeatures)&&p.fontFeatures.length?(y=p.fontFeatures,N=y.map(function(na){return na.name}),X=y.map(function(na){return na.value}),p._fontFeatureLen=y.length,p._fontFeatureNamesPtr=t(N),p._fontFeatureValuesPtr=n(X,"HEAPU32")):(p._fontFeatureLen=0,p._fontFeatureNamesPtr=K,p._fontFeatureValuesPtr=
|
||||
K);Array.isArray(p.fontVariations)&&p.fontVariations.length?(y=p.fontVariations,N=y.map(function(na){return na.axis}),X=y.map(function(na){return na.value}),p._fontVariationLen=y.length,p._fontVariationAxesPtr=t(N),p._fontVariationValuesPtr=n(X,"HEAPF32")):(p._fontVariationLen=0,p._fontVariationAxesPtr=K,p._fontVariationValuesPtr=K)}function C(p){g._free(p._fontFamiliesPtr);g._free(p._shadowColorsPtr);g._free(p._shadowOffsetsPtr);g._free(p._shadowBlurRadiiPtr);g._free(p._fontFeatureNamesPtr);g._free(p._fontFeatureValuesPtr);
|
||||
g._free(p._fontVariationAxesPtr);g._free(p._fontVariationValuesPtr)}g.Paragraph.prototype.getRectsForRange=function(p,y,N,X){p=this._getRectsForRange(p,y,N,X);return h(p)};g.Paragraph.prototype.getRectsForPlaceholders=function(){var p=this._getRectsForPlaceholders();return h(p)};g.Paragraph.prototype.getGlyphInfoAt=function(p){return d(this._getGlyphInfoAt(p))};g.Paragraph.prototype.getClosestGlyphInfoAtCoordinate=function(p,y){return d(this._getClosestGlyphInfoAtCoordinate(p,y))};g.TypefaceFontProvider.prototype.registerFont=
|
||||
function(p,y){p=g.Typeface.MakeTypefaceFromData(p);if(!p)return null;y=u(y);this._registerFont(p,y)};g.ParagraphStyle=function(p){p.disableHinting=p.disableHinting||!1;if(p.ellipsis){var y=p.ellipsis;p._ellipsisPtr=u(y);p._ellipsisLen=qa(y)}else p._ellipsisPtr=K,p._ellipsisLen=0;null==p.heightMultiplier&&(p.heightMultiplier=-1);p.maxLines=p.maxLines||0;p.replaceTabCharacters=p.replaceTabCharacters||!1;y=(y=p.strutStyle)||{};y.strutEnabled=y.strutEnabled||!1;y.strutEnabled&&Array.isArray(y.fontFamilies)&&
|
||||
y.fontFamilies.length?(y._fontFamiliesPtr=t(y.fontFamilies),y._fontFamiliesLen=y.fontFamilies.length):(y._fontFamiliesPtr=K,y._fontFamiliesLen=0);y.fontStyle=m(y.fontStyle);null==y.fontSize&&(y.fontSize=-1);null==y.heightMultiplier&&(y.heightMultiplier=-1);y.halfLeading=y.halfLeading||!1;y.leading=y.leading||0;y.forceStrutHeight=y.forceStrutHeight||!1;p.strutStyle=y;p.textAlign=p.textAlign||g.TextAlign.Start;p.textDirection=p.textDirection||g.TextDirection.LTR;p.textHeightBehavior=p.textHeightBehavior||
|
||||
g.TextHeightBehavior.All;p.textStyle=g.TextStyle(p.textStyle);p.applyRoundingHack=!1!==p.applyRoundingHack;return p};g.TextStyle=function(p){p.color||(p.color=g.BLACK);p.decoration=p.decoration||0;p.decorationThickness=p.decorationThickness||0;p.decorationStyle=p.decorationStyle||g.DecorationStyle.Solid;p.textBaseline=p.textBaseline||g.TextBaseline.Alphabetic;null==p.fontSize&&(p.fontSize=-1);p.letterSpacing=p.letterSpacing||0;p.wordSpacing=p.wordSpacing||0;null==p.heightMultiplier&&(p.heightMultiplier=
|
||||
-1);p.halfLeading=p.halfLeading||!1;p.fontStyle=m(p.fontStyle);return p};var G={},F=g._malloc(16),T=g._malloc(16),U=g._malloc(16);g.ParagraphBuilder.Make=function(p,y){x(p.textStyle);y=g.ParagraphBuilder._Make(p,y);C(p.textStyle);return y};g.ParagraphBuilder.MakeFromFontProvider=function(p,y){x(p.textStyle);y=g.ParagraphBuilder._MakeFromFontProvider(p,y);C(p.textStyle);return y};g.ParagraphBuilder.MakeFromFontCollection=function(p,y){x(p.textStyle);y=g.ParagraphBuilder._MakeFromFontCollection(p,y);
|
||||
C(p.textStyle);return y};g.ParagraphBuilder.ShapeText=function(p,y,N){let X=0;for(const xa of y)X+=xa.length;if(X!==p.length)throw"Accumulated block lengths must equal text.length";return g.ParagraphBuilder._ShapeText(p,y,N)};g.ParagraphBuilder.prototype.pushStyle=function(p){x(p);this._pushStyle(p);C(p)};g.ParagraphBuilder.prototype.pushPaintStyle=function(p,y,N){x(p);this._pushPaintStyle(p,y,N);C(p)};g.ParagraphBuilder.prototype.addPlaceholder=function(p,y,N,X,xa){N=N||g.PlaceholderAlignment.Baseline;
|
||||
X=X||g.TextBaseline.Alphabetic;this._addPlaceholder(p||0,y||0,N,X,xa||0)};g.ParagraphBuilder.prototype.setWordsUtf8=function(p){var y=n(p,"HEAPU32");this._setWordsUtf8(y,p&&p.length||0);k(y,p)};g.ParagraphBuilder.prototype.setWordsUtf16=function(p){var y=n(p,"HEAPU32");this._setWordsUtf16(y,p&&p.length||0);k(y,p)};g.ParagraphBuilder.prototype.setGraphemeBreaksUtf8=function(p){var y=n(p,"HEAPU32");this._setGraphemeBreaksUtf8(y,p&&p.length||0);k(y,p)};g.ParagraphBuilder.prototype.setGraphemeBreaksUtf16=
|
||||
function(p){var y=n(p,"HEAPU32");this._setGraphemeBreaksUtf16(y,p&&p.length||0);k(y,p)};g.ParagraphBuilder.prototype.setLineBreaksUtf8=function(p){var y=n(p,"HEAPU32");this._setLineBreaksUtf8(y,p&&p.length||0);k(y,p)};g.ParagraphBuilder.prototype.setLineBreaksUtf16=function(p){var y=n(p,"HEAPU32");this._setLineBreaksUtf16(y,p&&p.length||0);k(y,p)}})})(r);a.Xd=a.Xd||[];a.Xd.push(function(){a.Path.prototype.op=function(g,d){return this._op(g,d)?this:null};a.Path.prototype.simplify=function(){return this._simplify()?
|
||||
this:null}});a.Xd=a.Xd||[];a.Xd.push(function(){a.Canvas.prototype.drawText=function(g,d,h,m,t){var u=qa(g),x=a._malloc(u+1);ra(g,x,u+1);this._drawSimpleText(x,u,d,h,t,m);a._free(x)};a.Canvas.prototype.drawGlyphs=function(g,d,h,m,t,u){if(!(2*g.length<=d.length))throw"Not enough positions for the array of gyphs";a.Ud(this.Td);const x=n(g,"HEAPU16"),C=n(d,"HEAPF32");this._drawGlyphs(g.length,x,C,h,m,t,u);k(C,d);k(x,g)};a.Font.prototype.getGlyphBounds=function(g,d,h){var m=n(g,"HEAPU16"),t=a._malloc(16*
|
||||
g.length);this._getGlyphWidthBounds(m,g.length,K,t,d||null);d=new Float32Array(a.HEAPU8.buffer,t,4*g.length);k(m,g);if(h)return h.set(d),a._free(t),h;g=Float32Array.from(d);a._free(t);return g};a.Font.prototype.getGlyphIDs=function(g,d,h){d||(d=g.length);var m=qa(g)+1,t=a._malloc(m);ra(g,t,m);g=a._malloc(2*d);d=this._getGlyphIDs(t,m-1,d,g);a._free(t);if(0>d)return a._free(g),null;t=new Uint16Array(a.HEAPU8.buffer,g,d);if(h)return h.set(t),a._free(g),h;h=Uint16Array.from(t);a._free(g);return h};a.Font.prototype.getGlyphIntercepts=
|
||||
function(g,d,h,m){var t=n(g,"HEAPU16"),u=n(d,"HEAPF32");return this._getGlyphIntercepts(t,g.length,!(g&&g._ck),u,d.length,!(d&&d._ck),h,m)};a.Font.prototype.getGlyphWidths=function(g,d,h){var m=n(g,"HEAPU16"),t=a._malloc(4*g.length);this._getGlyphWidthBounds(m,g.length,t,K,d||null);d=new Float32Array(a.HEAPU8.buffer,t,g.length);k(m,g);if(h)return h.set(d),a._free(t),h;g=Float32Array.from(d);a._free(t);return g};a.FontMgr.FromData=function(){if(!arguments.length)return null;var g=arguments;1===g.length&&
|
||||
Array.isArray(g[0])&&(g=arguments[0]);if(!g.length)return null;for(var d=[],h=[],m=0;m<g.length;m++){var t=new Uint8Array(g[m]),u=n(t,"HEAPU8");d.push(u);h.push(t.byteLength)}d=n(d,"HEAPU32");h=n(h,"HEAPU32");g=a.FontMgr._fromData(d,h,g.length);a._free(d);a._free(h);return g};a.Typeface.MakeTypefaceFromData=function(g){g=new Uint8Array(g);var d=n(g,"HEAPU8");return(g=a.Typeface._MakeTypefaceFromData(d,g.byteLength))?g:null};a.Typeface.MakeFreeTypeFaceFromData=a.Typeface.MakeTypefaceFromData;a.Typeface.prototype.getGlyphIDs=
|
||||
function(g,d,h){d||(d=g.length);var m=qa(g)+1,t=a._malloc(m);ra(g,t,m);g=a._malloc(2*d);d=this._getGlyphIDs(t,m-1,d,g);a._free(t);if(0>d)return a._free(g),null;t=new Uint16Array(a.HEAPU8.buffer,g,d);if(h)return h.set(t),a._free(g),h;h=Uint16Array.from(t);a._free(g);return h};a.TextBlob.MakeOnPath=function(g,d,h,m){if(g&&g.length&&d&&d.countPoints()){if(1===d.countPoints())return this.MakeFromText(g,h);m||=0;var t=h.getGlyphIDs(g);t=h.getGlyphWidths(t);var u=[];d=new a.ContourMeasureIter(d,!1,1);for(var x=
|
||||
d.next(),C=new Float32Array(4),G=0;G<g.length&&x;G++){var F=t[G];m+=F/2;if(m>x.length()){x.delete();x=d.next();if(!x){g=g.substring(0,G);break}m=F/2}x.getPosTan(m,C);var T=C[2],U=C[3];u.push(T,U,C[0]-F/2*T,C[1]-F/2*U);m+=F/2}g=this.MakeFromRSXform(g,u,h);x&&x.delete();d.delete();return g}};a.TextBlob.MakeFromRSXform=function(g,d,h){var m=qa(g)+1,t=a._malloc(m);ra(g,t,m);g=n(d,"HEAPF32");h=a.TextBlob._MakeFromRSXform(t,m-1,g,h);a._free(t);return h?h:null};a.TextBlob.MakeFromRSXformGlyphs=function(g,
|
||||
d,h){var m=n(g,"HEAPU16");d=n(d,"HEAPF32");h=a.TextBlob._MakeFromRSXformGlyphs(m,2*g.length,d,h);k(m,g);return h?h:null};a.TextBlob.MakeFromGlyphs=function(g,d){var h=n(g,"HEAPU16");d=a.TextBlob._MakeFromGlyphs(h,2*g.length,d);k(h,g);return d?d:null};a.TextBlob.MakeFromText=function(g,d){var h=qa(g)+1,m=a._malloc(h);ra(g,m,h);g=a.TextBlob._MakeFromText(m,h-1,d);a._free(m);return g?g:null};a.MallocGlyphIDs=function(g){return a.Malloc(Uint16Array,g)}});a.Xd=a.Xd||[];a.Xd.push(function(){a.MakePicture=
|
||||
function(g){g=new Uint8Array(g);var d=a._malloc(g.byteLength);a.HEAPU8.set(g,d);return(g=a._MakePicture(d,g.byteLength))?g:null}});a.Xd=a.Xd||[];a.Xd.push(function(){a.RuntimeEffect.Make=function(g,d){return a.RuntimeEffect._Make(g,{onError:d||function(h){console.log("RuntimeEffect error",h)}})};a.RuntimeEffect.MakeForBlender=function(g,d){return a.RuntimeEffect._MakeForBlender(g,{onError:d||function(h){console.log("RuntimeEffect error",h)}})};a.RuntimeEffect.prototype.makeShader=function(g,d){var h=
|
||||
!g._ck,m=n(g,"HEAPF32");d=q(d);return this._makeShader(m,4*g.length,h,d)};a.RuntimeEffect.prototype.makeShaderWithChildren=function(g,d,h){var m=!g._ck,t=n(g,"HEAPF32");h=q(h);for(var u=[],x=0;x<d.length;x++)u.push(d[x].Sd.Vd);d=n(u,"HEAPU32");return this._makeShaderWithChildren(t,4*g.length,m,d,u.length,h)};a.RuntimeEffect.prototype.makeBlender=function(g){var d=!g._ck,h=n(g,"HEAPF32");return this._makeBlender(h,4*g.length,d)}})})(r);var sa=Object.assign({},r),ta="",ua,va;
|
||||
if(ea||ha)ha?ta=self.location.href:"undefined"!=typeof document&&document.currentScript&&(ta=document.currentScript.src),_scriptName&&(ta=_scriptName),ta.startsWith("blob:")?ta="":ta=ta.substr(0,ta.replace(/[?#].*/,"").lastIndexOf("/")+1),ha&&(va=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),ua=a=>fetch(a,{credentials:"same-origin"}).then(b=>b.ok?b.arrayBuffer():Promise.reject(Error(b.status+" : "+b.url)));
|
||||
var wa=console.log.bind(console),ya=console.error.bind(console);Object.assign(r,sa);sa=null;var za,Aa=!1,Ca,B,Da,Fa,E,H,J,Ga;function Ha(){var a=za.buffer;r.HEAP8=Ca=new Int8Array(a);r.HEAP16=Da=new Int16Array(a);r.HEAPU8=B=new Uint8Array(a);r.HEAPU16=Fa=new Uint16Array(a);r.HEAP32=E=new Int32Array(a);r.HEAPU32=H=new Uint32Array(a);r.HEAPF32=J=new Float32Array(a);r.HEAPF64=Ga=new Float64Array(a)}var Ia=[],Ja=[],Ka=[],La=0,Ma=null,Oa=null;
|
||||
function Pa(a){a="Aborted("+a+")";ya(a);Aa=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");ca(a);throw a;}var Qa=a=>a.startsWith("data:application/octet-stream;base64,"),Ra;function Sa(a){return ua(a).then(b=>new Uint8Array(b),()=>{if(va)var b=va(a);else throw"both async and sync fetching of the wasm failed";return b})}function Ta(a,b,c){return Sa(a).then(e=>WebAssembly.instantiate(e,b)).then(c,e=>{ya(`failed to asynchronously prepare wasm: ${e}`);Pa(e)})}
|
||||
function Ua(a,b){var c=Ra;return"function"!=typeof WebAssembly.instantiateStreaming||Qa(c)||"function"!=typeof fetch?Ta(c,a,b):fetch(c,{credentials:"same-origin"}).then(e=>WebAssembly.instantiateStreaming(e,a).then(b,function(f){ya(`wasm streaming compile failed: ${f}`);ya("falling back to ArrayBuffer instantiation");return Ta(c,a,b)}))}function Va(a){this.name="ExitStatus";this.message=`Program terminated with exit(${a})`;this.status=a}var Wa=a=>{a.forEach(b=>b(r))};
|
||||
class Xa{constructor(a){this.Vd=a-24}}
|
||||
var Ya=0,Za=0,bb="undefined"!=typeof TextDecoder?new TextDecoder:void 0,cb=(a,b=0,c=NaN)=>{var e=b+c;for(c=b;a[c]&&!(c>=e);)++c;if(16<c-b&&a.buffer&&bb)return bb.decode(a.subarray(b,c));for(e="";b<c;){var f=a[b++];if(f&128){var k=a[b++]&63;if(192==(f&224))e+=String.fromCharCode((f&31)<<6|k);else{var n=a[b++]&63;f=224==(f&240)?(f&15)<<12|k<<6|n:(f&7)<<18|k<<12|n<<6|a[b++]&63;65536>f?e+=String.fromCharCode(f):(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else e+=String.fromCharCode(f)}return e},
|
||||
db={},eb=a=>{for(;a.length;){var b=a.pop();a.pop()(b)}};function fb(a){return this.fromWireType(H[a>>2])}
|
||||
var gb={},hb={},ib={},jb,lb=(a,b,c)=>{function e(l){l=c(l);if(l.length!==a.length)throw new jb("Mismatched type converter count");for(var q=0;q<a.length;++q)kb(a[q],l[q])}a.forEach(l=>ib[l]=b);var f=Array(b.length),k=[],n=0;b.forEach((l,q)=>{hb.hasOwnProperty(l)?f[q]=hb[l]:(k.push(l),gb.hasOwnProperty(l)||(gb[l]=[]),gb[l].push(()=>{f[q]=hb[l];++n;n===k.length&&e(f)}))});0===k.length&&e(f)},mb,L=a=>{for(var b="";B[a];)b+=mb[B[a++]];return b},M;
|
||||
function nb(a,b,c={}){var e=b.name;if(!a)throw new M(`type "${e}" must have a positive integer typeid pointer`);if(hb.hasOwnProperty(a)){if(c.ef)return;throw new M(`Cannot register type '${e}' twice`);}hb[a]=b;delete ib[a];gb.hasOwnProperty(a)&&(b=gb[a],delete gb[a],b.forEach(f=>f()))}function kb(a,b,c={}){return nb(a,b,c)}
|
||||
var ob=a=>{throw new M(a.Sd.Yd.Wd.name+" instance already deleted");},pb=!1,qb=()=>{},rb=(a,b,c)=>{if(b===c)return a;if(void 0===c.ae)return null;a=rb(a,b,c.ae);return null===a?null:c.Xe(a)},sb={},tb={},zb=(a,b)=>{if(void 0===b)throw new M("ptr should not be undefined");for(;a.ae;)b=a.se(b),a=a.ae;return tb[b]},Bb=(a,b)=>{if(!b.Yd||!b.Vd)throw new jb("makeClassHandle requires ptr and ptrType");if(!!b.ce!==!!b.Zd)throw new jb("Both smartPtrType and smartPtr must be specified");b.count={value:1};return Ab(Object.create(a,
|
||||
{Sd:{value:b,writable:!0}}))},Ab=a=>{if("undefined"===typeof FinalizationRegistry)return Ab=b=>b,a;pb=new FinalizationRegistry(b=>{b=b.Sd;--b.count.value;0===b.count.value&&(b.Zd?b.ce.he(b.Zd):b.Yd.Wd.he(b.Vd))});Ab=b=>{var c=b.Sd;c.Zd&&pb.register(b,{Sd:c},b);return b};qb=b=>{pb.unregister(b)};return Ab(a)},Cb=[];function Db(){}
|
||||
var Eb=(a,b)=>Object.defineProperty(b,"name",{value:a}),Fb=(a,b,c)=>{if(void 0===a[b].$d){var e=a[b];a[b]=function(...f){if(!a[b].$d.hasOwnProperty(f.length))throw new M(`Function '${c}' called with an invalid number of arguments (${f.length}) - expects one of (${a[b].$d})!`);return a[b].$d[f.length].apply(this,f)};a[b].$d=[];a[b].$d[e.ie]=e}},Gb=(a,b,c)=>{if(r.hasOwnProperty(a)){if(void 0===c||void 0!==r[a].$d&&void 0!==r[a].$d[c])throw new M(`Cannot register public name '${a}' twice`);Fb(r,a,a);
|
||||
if(r[a].$d.hasOwnProperty(c))throw new M(`Cannot register multiple overloads of a function with the same number of arguments (${c})!`);r[a].$d[c]=b}else r[a]=b,r[a].ie=c},Hb=a=>{a=a.replace(/[^a-zA-Z0-9_]/g,"$");var b=a.charCodeAt(0);return 48<=b&&57>=b?`_${a}`:a};function Ib(a,b,c,e,f,k,n,l){this.name=a;this.constructor=b;this.me=c;this.he=e;this.ae=f;this.$e=k;this.se=n;this.Xe=l;this.hf=[]}
|
||||
var Jb=(a,b,c)=>{for(;b!==c;){if(!b.se)throw new M(`Expected null or instance of ${c.name}, got an instance of ${b.name}`);a=b.se(a);b=b.ae}return a};function Kb(a,b){if(null===b){if(this.Ee)throw new M(`null is not a valid ${this.name}`);return 0}if(!b.Sd)throw new M(`Cannot pass "${Lb(b)}" as a ${this.name}`);if(!b.Sd.Vd)throw new M(`Cannot pass deleted object as a pointer of type ${this.name}`);return Jb(b.Sd.Vd,b.Sd.Yd.Wd,this.Wd)}
|
||||
function Mb(a,b){if(null===b){if(this.Ee)throw new M(`null is not a valid ${this.name}`);if(this.xe){var c=this.Fe();null!==a&&a.push(this.he,c);return c}return 0}if(!b||!b.Sd)throw new M(`Cannot pass "${Lb(b)}" as a ${this.name}`);if(!b.Sd.Vd)throw new M(`Cannot pass deleted object as a pointer of type ${this.name}`);if(!this.we&&b.Sd.Yd.we)throw new M(`Cannot convert argument of type ${b.Sd.ce?b.Sd.ce.name:b.Sd.Yd.name} to parameter type ${this.name}`);c=Jb(b.Sd.Vd,b.Sd.Yd.Wd,this.Wd);if(this.xe){if(void 0===
|
||||
b.Sd.Zd)throw new M("Passing raw pointer to smart pointer is illegal");switch(this.nf){case 0:if(b.Sd.ce===this)c=b.Sd.Zd;else throw new M(`Cannot convert argument of type ${b.Sd.ce?b.Sd.ce.name:b.Sd.Yd.name} to parameter type ${this.name}`);break;case 1:c=b.Sd.Zd;break;case 2:if(b.Sd.ce===this)c=b.Sd.Zd;else{var e=b.clone();c=this.jf(c,Nb(()=>e["delete"]()));null!==a&&a.push(this.he,c)}break;default:throw new M("Unsupporting sharing policy");}}return c}
|
||||
function Ob(a,b){if(null===b){if(this.Ee)throw new M(`null is not a valid ${this.name}`);return 0}if(!b.Sd)throw new M(`Cannot pass "${Lb(b)}" as a ${this.name}`);if(!b.Sd.Vd)throw new M(`Cannot pass deleted object as a pointer of type ${this.name}`);if(b.Sd.Yd.we)throw new M(`Cannot convert argument of type ${b.Sd.Yd.name} to parameter type ${this.name}`);return Jb(b.Sd.Vd,b.Sd.Yd.Wd,this.Wd)}
|
||||
function Pb(a,b,c,e,f,k,n,l,q,v,w){this.name=a;this.Wd=b;this.Ee=c;this.we=e;this.xe=f;this.gf=k;this.nf=n;this.Me=l;this.Fe=q;this.jf=v;this.he=w;f||void 0!==b.ae?this.toWireType=Mb:(this.toWireType=e?Kb:Ob,this.ee=null)}
|
||||
var Qb=(a,b,c)=>{if(!r.hasOwnProperty(a))throw new jb("Replacing nonexistent public symbol");void 0!==r[a].$d&&void 0!==c?r[a].$d[c]=b:(r[a]=b,r[a].ie=c)},O,Rb=(a,b,c=[])=>{a.includes("j")?(a=a.replace(/p/g,"i"),b=(0,r["dynCall_"+a])(b,...c)):b=O.get(b)(...c);return b},Sb=(a,b)=>(...c)=>Rb(a,b,c),Tb=(a,b)=>{a=L(a);var c=a.includes("j")?Sb(a,b):O.get(b);if("function"!=typeof c)throw new M(`unknown function pointer with signature ${a}: ${b}`);return c},ac,dc=a=>{a=bc(a);var b=L(a);cc(a);return b},ec=
|
||||
(a,b)=>{function c(k){f[k]||hb[k]||(ib[k]?ib[k].forEach(c):(e.push(k),f[k]=!0))}var e=[],f={};b.forEach(c);throw new ac(`${a}: `+e.map(dc).join([", "]));};function fc(a){for(var b=1;b<a.length;++b)if(null!==a[b]&&void 0===a[b].ee)return!0;return!1}
|
||||
function gc(a,b,c,e,f){var k=b.length;if(2>k)throw new M("argTypes array size mismatch! Must at least get return value and 'this' types!");var n=null!==b[1]&&null!==c,l=fc(b),q="void"!==b[0].name,v=k-2,w=Array(v),z=[],D=[];return Eb(a,function(...I){D.length=0;z.length=n?2:1;z[0]=f;if(n){var Q=b[1].toWireType(D,this);z[1]=Q}for(var P=0;P<v;++P)w[P]=b[P+2].toWireType(D,I[P]),z.push(w[P]);I=e(...z);if(l)eb(D);else for(P=n?1:2;P<b.length;P++){var ba=1===P?Q:w[P-2];null!==b[P].ee&&b[P].ee(ba)}Q=q?b[0].fromWireType(I):
|
||||
void 0;return Q})}
|
||||
var hc=(a,b)=>{for(var c=[],e=0;e<a;e++)c.push(H[b+4*e>>2]);return c},ic=a=>{a=a.trim();const b=a.indexOf("(");return-1!==b?a.substr(0,b):a},jc=[],kc=[],lc=a=>{9<a&&0===--kc[a+1]&&(kc[a]=void 0,jc.push(a))},mc=a=>{if(!a)throw new M("Cannot use deleted val. handle = "+a);return kc[a]},Nb=a=>{switch(a){case void 0:return 2;case null:return 4;case !0:return 6;case !1:return 8;default:const b=jc.pop()||kc.length;kc[b]=a;kc[b+1]=1;return b}},nc={name:"emscripten::val",fromWireType:a=>{var b=mc(a);lc(a);
|
||||
return b},toWireType:(a,b)=>Nb(b),de:8,readValueFromPointer:fb,ee:null},oc=(a,b,c)=>{switch(b){case 1:return c?function(e){return this.fromWireType(Ca[e])}:function(e){return this.fromWireType(B[e])};case 2:return c?function(e){return this.fromWireType(Da[e>>1])}:function(e){return this.fromWireType(Fa[e>>1])};case 4:return c?function(e){return this.fromWireType(E[e>>2])}:function(e){return this.fromWireType(H[e>>2])};default:throw new TypeError(`invalid integer width (${b}): ${a}`);}},pc=(a,b)=>
|
||||
{var c=hb[a];if(void 0===c)throw a=`${b} has unknown type ${dc(a)}`,new M(a);return c},Lb=a=>{if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a},qc=(a,b)=>{switch(b){case 4:return function(c){return this.fromWireType(J[c>>2])};case 8:return function(c){return this.fromWireType(Ga[c>>3])};default:throw new TypeError(`invalid float width (${b}): ${a}`);}},rc=(a,b,c)=>{switch(b){case 1:return c?e=>Ca[e]:e=>B[e];case 2:return c?e=>Da[e>>1]:e=>Fa[e>>
|
||||
1];case 4:return c?e=>E[e>>2]:e=>H[e>>2];default:throw new TypeError(`invalid integer width (${b}): ${a}`);}},ra=(a,b,c)=>{var e=B;if(!(0<c))return 0;var f=b;c=b+c-1;for(var k=0;k<a.length;++k){var n=a.charCodeAt(k);if(55296<=n&&57343>=n){var l=a.charCodeAt(++k);n=65536+((n&1023)<<10)|l&1023}if(127>=n){if(b>=c)break;e[b++]=n}else{if(2047>=n){if(b+1>=c)break;e[b++]=192|n>>6}else{if(65535>=n){if(b+2>=c)break;e[b++]=224|n>>12}else{if(b+3>=c)break;e[b++]=240|n>>18;e[b++]=128|n>>12&63}e[b++]=128|n>>6&
|
||||
63}e[b++]=128|n&63}}e[b]=0;return b-f},qa=a=>{for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);127>=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++c):b+=3}return b},sc="undefined"!=typeof TextDecoder?new TextDecoder("utf-16le"):void 0,tc=(a,b)=>{var c=a>>1;for(var e=c+b/2;!(c>=e)&&Fa[c];)++c;c<<=1;if(32<c-a&&sc)return sc.decode(B.subarray(a,c));c="";for(e=0;!(e>=b/2);++e){var f=Da[a+2*e>>1];if(0==f)break;c+=String.fromCharCode(f)}return c},uc=(a,b,c)=>{c??=2147483647;if(2>c)return 0;c-=2;var e=
|
||||
b;c=c<2*a.length?c/2:a.length;for(var f=0;f<c;++f)Da[b>>1]=a.charCodeAt(f),b+=2;Da[b>>1]=0;return b-e},vc=a=>2*a.length,wc=(a,b)=>{for(var c=0,e="";!(c>=b/4);){var f=E[a+4*c>>2];if(0==f)break;++c;65536<=f?(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023)):e+=String.fromCharCode(f)}return e},xc=(a,b,c)=>{c??=2147483647;if(4>c)return 0;var e=b;c=e+c-4;for(var f=0;f<a.length;++f){var k=a.charCodeAt(f);if(55296<=k&&57343>=k){var n=a.charCodeAt(++f);k=65536+((k&1023)<<10)|n&1023}E[b>>2]=k;b+=
|
||||
4;if(b+4>c)break}E[b>>2]=0;return b-e},yc=a=>{for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);55296<=e&&57343>=e&&++c;b+=4}return b},zc=(a,b,c)=>{var e=[];a=a.toWireType(e,c);e.length&&(H[b>>2]=Nb(e));return a},Ac=[],Bc={},Cc=a=>{var b=Bc[a];return void 0===b?L(a):b},Dc=()=>{function a(b){b.$$$embind_global$$$=b;var c="object"==typeof $$$embind_global$$$&&b.$$$embind_global$$$==b;c||delete b.$$$embind_global$$$;return c}if("object"==typeof globalThis)return globalThis;if("object"==typeof $$$embind_global$$$)return $$$embind_global$$$;
|
||||
"object"==typeof global&&a(global)?$$$embind_global$$$=global:"object"==typeof self&&a(self)&&($$$embind_global$$$=self);if("object"==typeof $$$embind_global$$$)return $$$embind_global$$$;throw Error("unable to get global object.");},Ec=a=>{var b=Ac.length;Ac.push(a);return b},Fc=(a,b)=>{for(var c=Array(a),e=0;e<a;++e)c[e]=pc(H[b+4*e>>2],"parameter "+e);return c},Gc=Reflect.construct,R,Hc=a=>{var b=a.getExtension("ANGLE_instanced_arrays");b&&(a.vertexAttribDivisor=(c,e)=>b.vertexAttribDivisorANGLE(c,
|
||||
e),a.drawArraysInstanced=(c,e,f,k)=>b.drawArraysInstancedANGLE(c,e,f,k),a.drawElementsInstanced=(c,e,f,k,n)=>b.drawElementsInstancedANGLE(c,e,f,k,n))},Ic=a=>{var b=a.getExtension("OES_vertex_array_object");b&&(a.createVertexArray=()=>b.createVertexArrayOES(),a.deleteVertexArray=c=>b.deleteVertexArrayOES(c),a.bindVertexArray=c=>b.bindVertexArrayOES(c),a.isVertexArray=c=>b.isVertexArrayOES(c))},Jc=a=>{var b=a.getExtension("WEBGL_draw_buffers");b&&(a.drawBuffers=(c,e)=>b.drawBuffersWEBGL(c,e))},Kc=a=>
|
||||
{var b="ANGLE_instanced_arrays EXT_blend_minmax EXT_disjoint_timer_query EXT_frag_depth EXT_shader_texture_lod EXT_sRGB OES_element_index_uint OES_fbo_render_mipmap OES_standard_derivatives OES_texture_float OES_texture_half_float OES_texture_half_float_linear OES_vertex_array_object WEBGL_color_buffer_float WEBGL_depth_texture WEBGL_draw_buffers EXT_color_buffer_float EXT_conservative_depth EXT_disjoint_timer_query_webgl2 EXT_texture_norm16 NV_shader_noperspective_interpolation WEBGL_clip_cull_distance EXT_clip_control EXT_color_buffer_half_float EXT_depth_clamp EXT_float_blend EXT_polygon_offset_clamp EXT_texture_compression_bptc EXT_texture_compression_rgtc EXT_texture_filter_anisotropic KHR_parallel_shader_compile OES_texture_float_linear WEBGL_blend_func_extended WEBGL_compressed_texture_astc WEBGL_compressed_texture_etc WEBGL_compressed_texture_etc1 WEBGL_compressed_texture_s3tc WEBGL_compressed_texture_s3tc_srgb WEBGL_debug_renderer_info WEBGL_debug_shaders WEBGL_lose_context WEBGL_multi_draw WEBGL_polygon_mode".split(" ");
|
||||
return(a.getSupportedExtensions()||[]).filter(c=>b.includes(c))},Lc=1,Mc=[],Nc=[],Oc=[],Pc=[],ka=[],Qc=[],Rc=[],pa=[],Sc=[],Tc=[],Uc=[],Vc={},Xc={},Yc=4,Zc=0,ja=a=>{for(var b=Lc++,c=a.length;c<b;c++)a[c]=null;return b},$c=(a,b,c,e)=>{for(var f=0;f<a;f++){var k=R[c](),n=k&&ja(e);k?(k.name=n,e[n]=k):S||=1282;E[b+4*f>>2]=n}},la=(a,b)=>{a.He||(a.He=a.getContext,a.getContext=function(e,f){f=a.He(e,f);return"webgl"==e==f instanceof WebGLRenderingContext?f:null});var c=1<b.majorVersion?a.getContext("webgl2",
|
||||
b):a.getContext("webgl",b);return c?ad(c,b):0},ad=(a,b)=>{var c=ja(pa),e={handle:c,attributes:b,version:b.majorVersion,fe:a};a.canvas&&(a.canvas.Pe=e);pa[c]=e;("undefined"==typeof b.Ye||b.Ye)&&bd(e);return c},oa=a=>{A=pa[a];r.pf=R=A?.fe;return!(a&&!R)},bd=a=>{a||=A;if(!a.ff){a.ff=!0;var b=a.fe;b.tf=b.getExtension("WEBGL_multi_draw");b.rf=b.getExtension("EXT_polygon_offset_clamp");b.qf=b.getExtension("EXT_clip_control");b.vf=b.getExtension("WEBGL_polygon_mode");Hc(b);Ic(b);Jc(b);b.Je=b.getExtension("WEBGL_draw_instanced_base_vertex_base_instance");
|
||||
b.Le=b.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance");2<=a.version&&(b.ge=b.getExtension("EXT_disjoint_timer_query_webgl2"));if(2>a.version||!b.ge)b.ge=b.getExtension("EXT_disjoint_timer_query");Kc(b).forEach(c=>{c.includes("lose_context")||c.includes("debug")||b.getExtension(c)})}},A,S,cd=(a,b)=>{R.bindFramebuffer(a,Oc[b])},dd=a=>{R.bindVertexArray(Rc[a])},ed=a=>R.clear(a),fd=(a,b,c,e)=>R.clearColor(a,b,c,e),gd=a=>R.clearStencil(a),hd=(a,b)=>{for(var c=0;c<a;c++){var e=E[b+
|
||||
4*c>>2];R.deleteVertexArray(Rc[e]);Rc[e]=null}},jd=[],kd=(a,b)=>{$c(a,b,"createVertexArray",Rc)};function ld(){var a=Kc(R);return a=a.concat(a.map(b=>"GL_"+b))}
|
||||
var md=(a,b,c)=>{if(b){var e=void 0;switch(a){case 36346:e=1;break;case 36344:0!=c&&1!=c&&(S||=1280);return;case 34814:case 36345:e=0;break;case 34466:var f=R.getParameter(34467);e=f?f.length:0;break;case 33309:if(2>A.version){S||=1282;return}e=ld().length;break;case 33307:case 33308:if(2>A.version){S||=1280;return}e=33307==a?3:0}if(void 0===e)switch(f=R.getParameter(a),typeof f){case "number":e=f;break;case "boolean":e=f?1:0;break;case "string":S||=1280;return;case "object":if(null===f)switch(a){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:e=
|
||||
0;break;default:S||=1280;return}else{if(f instanceof Float32Array||f instanceof Uint32Array||f instanceof Int32Array||f instanceof Array){for(a=0;a<f.length;++a)switch(c){case 0:E[b+4*a>>2]=f[a];break;case 2:J[b+4*a>>2]=f[a];break;case 4:Ca[b+a]=f[a]?1:0}return}try{e=f.name|0}catch(k){S||=1280;ya(`GL_INVALID_ENUM in glGet${c}v: Unknown object returned from WebGL getParameter(${a})! (error: ${k})`);return}}break;default:S||=1280;ya(`GL_INVALID_ENUM in glGet${c}v: Native code calling glGet${c}v(${a}) and it returns ${f} of type ${typeof f}!`);
|
||||
return}switch(c){case 1:c=e;H[b>>2]=c;H[b+4>>2]=(c-H[b>>2])/4294967296;break;case 0:E[b>>2]=e;break;case 2:J[b>>2]=e;break;case 4:Ca[b]=e?1:0}}else S||=1281},nd=(a,b)=>md(a,b,0),od=(a,b,c)=>{if(c){a=Sc[a];b=2>A.version?R.ge.getQueryObjectEXT(a,b):R.getQueryParameter(a,b);var e;"boolean"==typeof b?e=b?1:0:e=b;H[c>>2]=e;H[c+4>>2]=(e-H[c>>2])/4294967296}else S||=1281},qd=a=>{var b=qa(a)+1,c=pd(b);c&&ra(a,c,b);return c},rd=a=>{var b=Vc[a];if(!b){switch(a){case 7939:b=qd(ld().join(" "));break;case 7936:case 7937:case 37445:case 37446:(b=
|
||||
R.getParameter(a))||(S||=1280);b=b?qd(b):0;break;case 7938:b=R.getParameter(7938);var c=`OpenGL ES 2.0 (${b})`;2<=A.version&&(c=`OpenGL ES 3.0 (${b})`);b=qd(c);break;case 35724:b=R.getParameter(35724);c=b.match(/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/);null!==c&&(3==c[1].length&&(c[1]+="0"),b=`OpenGL ES GLSL ES ${c[1]} (${b})`);b=qd(b);break;default:S||=1280}Vc[a]=b}return b},sd=(a,b)=>{if(2>A.version)return S||=1282,0;var c=Xc[a];if(c)return 0>b||b>=c.length?(S||=1281,0):c[b];switch(a){case 7939:return c=
|
||||
ld().map(qd),c=Xc[a]=c,0>b||b>=c.length?(S||=1281,0):c[b];default:return S||=1280,0}},td=a=>"]"==a.slice(-1)&&a.lastIndexOf("["),ud=a=>{a-=5120;return 0==a?Ca:1==a?B:2==a?Da:4==a?E:6==a?J:5==a||28922==a||28520==a||30779==a||30782==a?H:Fa},vd=(a,b,c,e,f)=>{a=ud(a);b=e*((Zc||c)*({5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4}[b-6402]||1)*a.BYTES_PER_ELEMENT+Yc-1&-Yc);return a.subarray(f>>>31-Math.clz32(a.BYTES_PER_ELEMENT),f+b>>>31-Math.clz32(a.BYTES_PER_ELEMENT))},V=a=>{var b=R.We;if(b){var c=
|
||||
b.re[a];"number"==typeof c&&(b.re[a]=c=R.getUniformLocation(b,b.Ne[a]+(0<c?`[${c}]`:"")));return c}S||=1282},wd=[],xd=[],yd={},Ad=()=>{if(!zd){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:"./this.program"},b;for(b in yd)void 0===yd[b]?delete a[b]:a[b]=yd[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);zd=c}return zd},zd,Bd=[null,[],[]];
|
||||
jb=r.InternalError=class extends Error{constructor(a){super(a);this.name="InternalError"}};for(var Cd=Array(256),Dd=0;256>Dd;++Dd)Cd[Dd]=String.fromCharCode(Dd);mb=Cd;M=r.BindingError=class extends Error{constructor(a){super(a);this.name="BindingError"}};
|
||||
Object.assign(Db.prototype,{isAliasOf:function(a){if(!(this instanceof Db&&a instanceof Db))return!1;var b=this.Sd.Yd.Wd,c=this.Sd.Vd;a.Sd=a.Sd;var e=a.Sd.Yd.Wd;for(a=a.Sd.Vd;b.ae;)c=b.se(c),b=b.ae;for(;e.ae;)a=e.se(a),e=e.ae;return b===e&&c===a},clone:function(){this.Sd.Vd||ob(this);if(this.Sd.qe)return this.Sd.count.value+=1,this;var a=Ab,b=Object,c=b.create,e=Object.getPrototypeOf(this),f=this.Sd;a=a(c.call(b,e,{Sd:{value:{count:f.count,pe:f.pe,qe:f.qe,Vd:f.Vd,Yd:f.Yd,Zd:f.Zd,ce:f.ce}}}));a.Sd.count.value+=
|
||||
1;a.Sd.pe=!1;return a},["delete"](){this.Sd.Vd||ob(this);if(this.Sd.pe&&!this.Sd.qe)throw new M("Object already scheduled for deletion");qb(this);var a=this.Sd;--a.count.value;0===a.count.value&&(a.Zd?a.ce.he(a.Zd):a.Yd.Wd.he(a.Vd));this.Sd.qe||(this.Sd.Zd=void 0,this.Sd.Vd=void 0)},isDeleted:function(){return!this.Sd.Vd},deleteLater:function(){this.Sd.Vd||ob(this);if(this.Sd.pe&&!this.Sd.qe)throw new M("Object already scheduled for deletion");Cb.push(this);this.Sd.pe=!0;return this}});
|
||||
Object.assign(Pb.prototype,{af(a){this.Me&&(a=this.Me(a));return a},Ie(a){this.he?.(a)},de:8,readValueFromPointer:fb,fromWireType:function(a){function b(){return this.xe?Bb(this.Wd.me,{Yd:this.gf,Vd:c,ce:this,Zd:a}):Bb(this.Wd.me,{Yd:this,Vd:a})}var c=this.af(a);if(!c)return this.Ie(a),null;var e=zb(this.Wd,c);if(void 0!==e){if(0===e.Sd.count.value)return e.Sd.Vd=c,e.Sd.Zd=a,e.clone();e=e.clone();this.Ie(a);return e}e=this.Wd.$e(c);e=sb[e];if(!e)return b.call(this);e=this.we?e.Ve:e.pointerType;var f=
|
||||
rb(c,this.Wd,e.Wd);return null===f?b.call(this):this.xe?Bb(e.Wd.me,{Yd:e,Vd:f,ce:this,Zd:a}):Bb(e.Wd.me,{Yd:e,Vd:f})}});ac=r.UnboundTypeError=((a,b)=>{var c=Eb(b,function(e){this.name=b;this.message=e;e=Error(e).stack;void 0!==e&&(this.stack=this.toString()+"\n"+e.replace(/^Error(:[^\n]*)?\n/,""))});c.prototype=Object.create(a.prototype);c.prototype.constructor=c;c.prototype.toString=function(){return void 0===this.message?this.name:`${this.name}: ${this.message}`};return c})(Error,"UnboundTypeError");
|
||||
kc.push(0,1,void 0,1,null,1,!0,1,!1,1);r.count_emval_handles=()=>kc.length/2-5-jc.length;for(var Ed=0;32>Ed;++Ed)jd.push(Array(Ed));var Fd=new Float32Array(288);for(Ed=0;288>=Ed;++Ed)wd[Ed]=Fd.subarray(0,Ed);var Gd=new Int32Array(288);for(Ed=0;288>=Ed;++Ed)xd[Ed]=Gd.subarray(0,Ed);
|
||||
var Vd={F:(a,b,c)=>{var e=new Xa(a);H[e.Vd+16>>2]=0;H[e.Vd+4>>2]=b;H[e.Vd+8>>2]=c;Ya=a;Za++;throw Ya;},U:function(){return 0},ud:()=>{},td:function(){return 0},sd:()=>{},rd:function(){},qd:()=>{},md:()=>{Pa("")},B:a=>{var b=db[a];delete db[a];var c=b.Fe,e=b.he,f=b.Ke,k=f.map(n=>n.df).concat(f.map(n=>n.lf));lb([a],k,n=>{var l={};f.forEach((q,v)=>{var w=n[v],z=q.bf,D=q.cf,I=n[v+f.length],Q=q.kf,P=q.mf;l[q.Ze]={read:ba=>w.fromWireType(z(D,ba)),write:(ba,ma)=>{var Y=[];Q(P,ba,I.toWireType(Y,ma));eb(Y)}}});
|
||||
return[{name:b.name,fromWireType:q=>{var v={},w;for(w in l)v[w]=l[w].read(q);e(q);return v},toWireType:(q,v)=>{for(var w in l)if(!(w in v))throw new TypeError(`Missing field: "${w}"`);var z=c();for(w in l)l[w].write(z,v[w]);null!==q&&q.push(e,z);return z},de:8,readValueFromPointer:fb,ee:e}]})},X:()=>{},ld:(a,b,c,e)=>{b=L(b);kb(a,{name:b,fromWireType:function(f){return!!f},toWireType:function(f,k){return k?c:e},de:8,readValueFromPointer:function(f){return this.fromWireType(B[f])},ee:null})},l:(a,b,
|
||||
c,e,f,k,n,l,q,v,w,z,D)=>{w=L(w);k=Tb(f,k);l&&=Tb(n,l);v&&=Tb(q,v);D=Tb(z,D);var I=Hb(w);Gb(I,function(){ec(`Cannot construct ${w} due to unbound types`,[e])});lb([a,b,c],e?[e]:[],Q=>{Q=Q[0];if(e){var P=Q.Wd;var ba=P.me}else ba=Db.prototype;Q=Eb(w,function(...Ea){if(Object.getPrototypeOf(this)!==ma)throw new M("Use 'new' to construct "+w);if(void 0===Y.je)throw new M(w+" has no accessible constructor");var fa=Y.je[Ea.length];if(void 0===fa)throw new M(`Tried to invoke ctor of ${w} with invalid number of parameters (${Ea.length}) - expected (${Object.keys(Y.je).toString()}) parameters instead!`);
|
||||
return fa.apply(this,Ea)});var ma=Object.create(ba,{constructor:{value:Q}});Q.prototype=ma;var Y=new Ib(w,Q,ma,D,P,k,l,v);if(Y.ae){var ia;(ia=Y.ae).te??(ia.te=[]);Y.ae.te.push(Y)}P=new Pb(w,Y,!0,!1,!1);ia=new Pb(w+"*",Y,!1,!1,!1);ba=new Pb(w+" const*",Y,!1,!0,!1);sb[a]={pointerType:ia,Ve:ba};Qb(I,Q);return[P,ia,ba]})},e:(a,b,c,e,f,k,n)=>{var l=hc(c,e);b=L(b);b=ic(b);k=Tb(f,k);lb([],[a],q=>{function v(){ec(`Cannot call ${w} due to unbound types`,l)}q=q[0];var w=`${q.name}.${b}`;b.startsWith("@@")&&
|
||||
(b=Symbol[b.substring(2)]);var z=q.Wd.constructor;void 0===z[b]?(v.ie=c-1,z[b]=v):(Fb(z,b,w),z[b].$d[c-1]=v);lb([],l,D=>{D=[D[0],null].concat(D.slice(1));D=gc(w,D,null,k,n);void 0===z[b].$d?(D.ie=c-1,z[b]=D):z[b].$d[c-1]=D;if(q.Wd.te)for(const I of q.Wd.te)I.constructor.hasOwnProperty(b)||(I.constructor[b]=D);return[]});return[]})},z:(a,b,c,e,f,k)=>{var n=hc(b,c);f=Tb(e,f);lb([],[a],l=>{l=l[0];var q=`constructor ${l.name}`;void 0===l.Wd.je&&(l.Wd.je=[]);if(void 0!==l.Wd.je[b-1])throw new M(`Cannot register multiple constructors with identical number of parameters (${b-
|
||||
1}) for class '${l.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`);l.Wd.je[b-1]=()=>{ec(`Cannot construct ${l.name} due to unbound types`,n)};lb([],n,v=>{v.splice(1,0,null);l.Wd.je[b-1]=gc(q,v,null,f,k);return[]});return[]})},a:(a,b,c,e,f,k,n,l)=>{var q=hc(c,e);b=L(b);b=ic(b);k=Tb(f,k);lb([],[a],v=>{function w(){ec(`Cannot call ${z} due to unbound types`,q)}v=v[0];var z=`${v.name}.${b}`;b.startsWith("@@")&&(b=Symbol[b.substring(2)]);l&&v.Wd.hf.push(b);
|
||||
var D=v.Wd.me,I=D[b];void 0===I||void 0===I.$d&&I.className!==v.name&&I.ie===c-2?(w.ie=c-2,w.className=v.name,D[b]=w):(Fb(D,b,z),D[b].$d[c-2]=w);lb([],q,Q=>{Q=gc(z,Q,v,k,n);void 0===D[b].$d?(Q.ie=c-2,D[b]=Q):D[b].$d[c-2]=Q;return[]});return[]})},q:(a,b,c)=>{a=L(a);lb([],[b],e=>{e=e[0];r[a]=e.fromWireType(c);return[]})},kd:a=>kb(a,nc),j:(a,b,c,e)=>{function f(){}b=L(b);f.values={};kb(a,{name:b,constructor:f,fromWireType:function(k){return this.constructor.values[k]},toWireType:(k,n)=>n.value,de:8,
|
||||
readValueFromPointer:oc(b,c,e),ee:null});Gb(b,f)},b:(a,b,c)=>{var e=pc(a,"enum");b=L(b);a=e.constructor;e=Object.create(e.constructor.prototype,{value:{value:c},constructor:{value:Eb(`${e.name}_${b}`,function(){})}});a.values[c]=e;a[b]=e},R:(a,b,c)=>{b=L(b);kb(a,{name:b,fromWireType:e=>e,toWireType:(e,f)=>f,de:8,readValueFromPointer:qc(b,c),ee:null})},w:(a,b,c,e,f,k)=>{var n=hc(b,c);a=L(a);a=ic(a);f=Tb(e,f);Gb(a,function(){ec(`Cannot call ${a} due to unbound types`,n)},b-1);lb([],n,l=>{l=[l[0],null].concat(l.slice(1));
|
||||
Qb(a,gc(a,l,null,f,k),b-1);return[]})},C:(a,b,c,e,f)=>{b=L(b);-1===f&&(f=4294967295);f=l=>l;if(0===e){var k=32-8*c;f=l=>l<<k>>>k}var n=b.includes("unsigned")?function(l,q){return q>>>0}:function(l,q){return q};kb(a,{name:b,fromWireType:f,toWireType:n,de:8,readValueFromPointer:rc(b,c,0!==e),ee:null})},p:(a,b,c)=>{function e(k){return new f(Ca.buffer,H[k+4>>2],H[k>>2])}var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=L(c);kb(a,{name:c,fromWireType:e,
|
||||
de:8,readValueFromPointer:e},{ef:!0})},o:(a,b,c,e,f,k,n,l,q,v,w,z)=>{c=L(c);k=Tb(f,k);l=Tb(n,l);v=Tb(q,v);z=Tb(w,z);lb([a],[b],D=>{D=D[0];return[new Pb(c,D.Wd,!1,!1,!0,D,e,k,l,v,z)]})},Q:(a,b)=>{b=L(b);var c="std::string"===b;kb(a,{name:b,fromWireType:function(e){var f=H[e>>2],k=e+4;if(c)for(var n=k,l=0;l<=f;++l){var q=k+l;if(l==f||0==B[q]){n=n?cb(B,n,q-n):"";if(void 0===v)var v=n;else v+=String.fromCharCode(0),v+=n;n=q+1}}else{v=Array(f);for(l=0;l<f;++l)v[l]=String.fromCharCode(B[k+l]);v=v.join("")}cc(e);
|
||||
return v},toWireType:function(e,f){f instanceof ArrayBuffer&&(f=new Uint8Array(f));var k="string"==typeof f;if(!(k||f instanceof Uint8Array||f instanceof Uint8ClampedArray||f instanceof Int8Array))throw new M("Cannot pass non-string to std::string");var n=c&&k?qa(f):f.length;var l=pd(4+n+1),q=l+4;H[l>>2]=n;if(c&&k)ra(f,q,n+1);else if(k)for(k=0;k<n;++k){var v=f.charCodeAt(k);if(255<v)throw cc(q),new M("String has UTF-16 code units that do not fit in 8 bits");B[q+k]=v}else for(k=0;k<n;++k)B[q+k]=f[k];
|
||||
null!==e&&e.push(cc,l);return l},de:8,readValueFromPointer:fb,ee(e){cc(e)}})},M:(a,b,c)=>{c=L(c);if(2===b){var e=tc;var f=uc;var k=vc;var n=l=>Fa[l>>1]}else 4===b&&(e=wc,f=xc,k=yc,n=l=>H[l>>2]);kb(a,{name:c,fromWireType:l=>{for(var q=H[l>>2],v,w=l+4,z=0;z<=q;++z){var D=l+4+z*b;if(z==q||0==n(D))w=e(w,D-w),void 0===v?v=w:(v+=String.fromCharCode(0),v+=w),w=D+b}cc(l);return v},toWireType:(l,q)=>{if("string"!=typeof q)throw new M(`Cannot pass non-string to C++ string type ${c}`);var v=k(q),w=pd(4+v+b);
|
||||
H[w>>2]=v/b;f(q,w+4,v+b);null!==l&&l.push(cc,w);return w},de:8,readValueFromPointer:fb,ee(l){cc(l)}})},A:(a,b,c,e,f,k)=>{db[a]={name:L(b),Fe:Tb(c,e),he:Tb(f,k),Ke:[]}},d:(a,b,c,e,f,k,n,l,q,v)=>{db[a].Ke.push({Ze:L(b),df:c,bf:Tb(e,f),cf:k,lf:n,kf:Tb(l,q),mf:v})},jd:(a,b)=>{b=L(b);kb(a,{sf:!0,name:b,de:0,fromWireType:()=>{},toWireType:()=>{}})},id:()=>1,hd:()=>{throw Infinity;},E:(a,b,c)=>{a=mc(a);b=pc(b,"emval::as");return zc(b,c,a)},L:(a,b,c,e)=>{a=Ac[a];b=mc(b);return a(null,b,c,e)},t:(a,b,c,e,f)=>
|
||||
{a=Ac[a];b=mc(b);c=Cc(c);return a(b,b[c],e,f)},c:lc,K:a=>{if(0===a)return Nb(Dc());a=Cc(a);return Nb(Dc()[a])},n:(a,b,c)=>{var e=Fc(a,b),f=e.shift();a--;var k=Array(a);b=`methodCaller<(${e.map(n=>n.name).join(", ")}) => ${f.name}>`;return Ec(Eb(b,(n,l,q,v)=>{for(var w=0,z=0;z<a;++z)k[z]=e[z].readValueFromPointer(v+w),w+=e[z].de;n=1===c?Gc(l,k):l.apply(n,k);return zc(f,q,n)}))},y:(a,b)=>{a=mc(a);b=mc(b);return Nb(a[b])},H:a=>{9<a&&(kc[a+1]+=1)},G:()=>Nb([]),f:a=>Nb(Cc(a)),D:()=>Nb({}),gd:a=>{a=mc(a);
|
||||
return!a},m:a=>{var b=mc(a);eb(b);lc(a)},h:(a,b,c)=>{a=mc(a);b=mc(b);c=mc(c);a[b]=c},g:(a,b)=>{a=pc(a,"_emval_take_value");a=a.readValueFromPointer(b);return Nb(a)},W:function(){return-52},V:function(){},fd:(a,b,c,e)=>{var f=(new Date).getFullYear(),k=(new Date(f,0,1)).getTimezoneOffset();f=(new Date(f,6,1)).getTimezoneOffset();H[a>>2]=60*Math.max(k,f);E[b>>2]=Number(k!=f);b=n=>{var l=Math.abs(n);return`UTC${0<=n?"-":"+"}${String(Math.floor(l/60)).padStart(2,"0")}${String(l%60).padStart(2,"0")}`};
|
||||
a=b(k);b=b(f);f<k?(ra(a,c,17),ra(b,e,17)):(ra(a,e,17),ra(b,c,17))},ed:()=>performance.now(),dd:a=>R.activeTexture(a),cd:(a,b)=>{R.attachShader(Nc[a],Qc[b])},bd:(a,b)=>{R.beginQuery(a,Sc[b])},ad:(a,b)=>{R.ge.beginQueryEXT(a,Sc[b])},$c:(a,b,c)=>{R.bindAttribLocation(Nc[a],b,c?cb(B,c):"")},_c:(a,b)=>{35051==a?R.Ce=b:35052==a&&(R.le=b);R.bindBuffer(a,Mc[b])},Zc:cd,Yc:(a,b)=>{R.bindRenderbuffer(a,Pc[b])},Xc:(a,b)=>{R.bindSampler(a,Tc[b])},Wc:(a,b)=>{R.bindTexture(a,ka[b])},Vc:dd,Uc:dd,Tc:(a,b,c,e)=>R.blendColor(a,
|
||||
b,c,e),Sc:a=>R.blendEquation(a),Rc:(a,b)=>R.blendFunc(a,b),Qc:(a,b,c,e,f,k,n,l,q,v)=>R.blitFramebuffer(a,b,c,e,f,k,n,l,q,v),Pc:(a,b,c,e)=>{2<=A.version?c&&b?R.bufferData(a,B,e,c,b):R.bufferData(a,b,e):R.bufferData(a,c?B.subarray(c,c+b):b,e)},Oc:(a,b,c,e)=>{2<=A.version?c&&R.bufferSubData(a,b,B,e,c):R.bufferSubData(a,b,B.subarray(e,e+c))},Nc:a=>R.checkFramebufferStatus(a),Mc:ed,Lc:fd,Kc:gd,Jc:(a,b,c,e)=>R.clientWaitSync(Uc[a],b,(c>>>0)+4294967296*e),Ic:(a,b,c,e)=>{R.colorMask(!!a,!!b,!!c,!!e)},Hc:a=>
|
||||
{R.compileShader(Qc[a])},Gc:(a,b,c,e,f,k,n,l)=>{2<=A.version?R.le||!n?R.compressedTexImage2D(a,b,c,e,f,k,n,l):R.compressedTexImage2D(a,b,c,e,f,k,B,l,n):R.compressedTexImage2D(a,b,c,e,f,k,B.subarray(l,l+n))},Fc:(a,b,c,e,f,k,n,l,q)=>{2<=A.version?R.le||!l?R.compressedTexSubImage2D(a,b,c,e,f,k,n,l,q):R.compressedTexSubImage2D(a,b,c,e,f,k,n,B,q,l):R.compressedTexSubImage2D(a,b,c,e,f,k,n,B.subarray(q,q+l))},Ec:(a,b,c,e,f)=>R.copyBufferSubData(a,b,c,e,f),Dc:(a,b,c,e,f,k,n,l)=>R.copyTexSubImage2D(a,b,c,
|
||||
e,f,k,n,l),Cc:()=>{var a=ja(Nc),b=R.createProgram();b.name=a;b.Ae=b.ye=b.ze=0;b.Ge=1;Nc[a]=b;return a},Bc:a=>{var b=ja(Qc);Qc[b]=R.createShader(a);return b},Ac:a=>R.cullFace(a),zc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Mc[e];f&&(R.deleteBuffer(f),f.name=0,Mc[e]=null,e==R.Ce&&(R.Ce=0),e==R.le&&(R.le=0))}},yc:(a,b)=>{for(var c=0;c<a;++c){var e=E[b+4*c>>2],f=Oc[e];f&&(R.deleteFramebuffer(f),f.name=0,Oc[e]=null)}},xc:a=>{if(a){var b=Nc[a];b?(R.deleteProgram(b),b.name=0,Nc[a]=null):S||=1281}},
|
||||
wc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Sc[e];f&&(R.deleteQuery(f),Sc[e]=null)}},vc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Sc[e];f&&(R.ge.deleteQueryEXT(f),Sc[e]=null)}},uc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Pc[e];f&&(R.deleteRenderbuffer(f),f.name=0,Pc[e]=null)}},tc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=Tc[e];f&&(R.deleteSampler(f),f.name=0,Tc[e]=null)}},sc:a=>{if(a){var b=Qc[a];b?(R.deleteShader(b),Qc[a]=null):S||=1281}},rc:a=>{if(a){var b=Uc[a];b?
|
||||
(R.deleteSync(b),b.name=0,Uc[a]=null):S||=1281}},qc:(a,b)=>{for(var c=0;c<a;c++){var e=E[b+4*c>>2],f=ka[e];f&&(R.deleteTexture(f),f.name=0,ka[e]=null)}},pc:hd,oc:hd,nc:a=>{R.depthMask(!!a)},mc:a=>R.disable(a),lc:a=>{R.disableVertexAttribArray(a)},kc:(a,b,c)=>{R.drawArrays(a,b,c)},jc:(a,b,c,e)=>{R.drawArraysInstanced(a,b,c,e)},ic:(a,b,c,e,f)=>{R.Je.drawArraysInstancedBaseInstanceWEBGL(a,b,c,e,f)},hc:(a,b)=>{for(var c=jd[a],e=0;e<a;e++)c[e]=E[b+4*e>>2];R.drawBuffers(c)},gc:(a,b,c,e)=>{R.drawElements(a,
|
||||
b,c,e)},fc:(a,b,c,e,f)=>{R.drawElementsInstanced(a,b,c,e,f)},ec:(a,b,c,e,f,k,n)=>{R.Je.drawElementsInstancedBaseVertexBaseInstanceWEBGL(a,b,c,e,f,k,n)},dc:(a,b,c,e,f,k)=>{R.drawElements(a,e,f,k)},cc:a=>R.enable(a),bc:a=>{R.enableVertexAttribArray(a)},ac:a=>R.endQuery(a),$b:a=>{R.ge.endQueryEXT(a)},_b:(a,b)=>(a=R.fenceSync(a,b))?(b=ja(Uc),a.name=b,Uc[b]=a,b):0,Zb:()=>R.finish(),Yb:()=>R.flush(),Xb:(a,b,c,e)=>{R.framebufferRenderbuffer(a,b,c,Pc[e])},Wb:(a,b,c,e,f)=>{R.framebufferTexture2D(a,b,c,ka[e],
|
||||
f)},Vb:a=>R.frontFace(a),Ub:(a,b)=>{$c(a,b,"createBuffer",Mc)},Tb:(a,b)=>{$c(a,b,"createFramebuffer",Oc)},Sb:(a,b)=>{$c(a,b,"createQuery",Sc)},Rb:(a,b)=>{for(var c=0;c<a;c++){var e=R.ge.createQueryEXT();if(!e){for(S||=1282;c<a;)E[b+4*c++>>2]=0;break}var f=ja(Sc);e.name=f;Sc[f]=e;E[b+4*c>>2]=f}},Qb:(a,b)=>{$c(a,b,"createRenderbuffer",Pc)},Pb:(a,b)=>{$c(a,b,"createSampler",Tc)},Ob:(a,b)=>{$c(a,b,"createTexture",ka)},Nb:kd,Mb:kd,Lb:a=>R.generateMipmap(a),Kb:(a,b,c)=>{c?E[c>>2]=R.getBufferParameter(a,
|
||||
b):S||=1281},Jb:()=>{var a=R.getError()||S;S=0;return a},Ib:(a,b)=>md(a,b,2),Hb:(a,b,c,e)=>{a=R.getFramebufferAttachmentParameter(a,b,c);if(a instanceof WebGLRenderbuffer||a instanceof WebGLTexture)a=a.name|0;E[e>>2]=a},Gb:nd,Fb:(a,b,c,e)=>{a=R.getProgramInfoLog(Nc[a]);null===a&&(a="(unknown error)");b=0<b&&e?ra(a,e,b):0;c&&(E[c>>2]=b)},Eb:(a,b,c)=>{if(c)if(a>=Lc)S||=1281;else if(a=Nc[a],35716==b)a=R.getProgramInfoLog(a),null===a&&(a="(unknown error)"),E[c>>2]=a.length+1;else if(35719==b){if(!a.Ae){var e=
|
||||
R.getProgramParameter(a,35718);for(b=0;b<e;++b)a.Ae=Math.max(a.Ae,R.getActiveUniform(a,b).name.length+1)}E[c>>2]=a.Ae}else if(35722==b){if(!a.ye)for(e=R.getProgramParameter(a,35721),b=0;b<e;++b)a.ye=Math.max(a.ye,R.getActiveAttrib(a,b).name.length+1);E[c>>2]=a.ye}else if(35381==b){if(!a.ze)for(e=R.getProgramParameter(a,35382),b=0;b<e;++b)a.ze=Math.max(a.ze,R.getActiveUniformBlockName(a,b).length+1);E[c>>2]=a.ze}else E[c>>2]=R.getProgramParameter(a,b);else S||=1281},Db:od,Cb:od,Bb:(a,b,c)=>{if(c){a=
|
||||
R.getQueryParameter(Sc[a],b);var e;"boolean"==typeof a?e=a?1:0:e=a;E[c>>2]=e}else S||=1281},Ab:(a,b,c)=>{if(c){a=R.ge.getQueryObjectEXT(Sc[a],b);var e;"boolean"==typeof a?e=a?1:0:e=a;E[c>>2]=e}else S||=1281},zb:(a,b,c)=>{c?E[c>>2]=R.getQuery(a,b):S||=1281},yb:(a,b,c)=>{c?E[c>>2]=R.ge.getQueryEXT(a,b):S||=1281},xb:(a,b,c)=>{c?E[c>>2]=R.getRenderbufferParameter(a,b):S||=1281},wb:(a,b,c,e)=>{a=R.getShaderInfoLog(Qc[a]);null===a&&(a="(unknown error)");b=0<b&&e?ra(a,e,b):0;c&&(E[c>>2]=b)},vb:(a,b,c,e)=>
|
||||
{a=R.getShaderPrecisionFormat(a,b);E[c>>2]=a.rangeMin;E[c+4>>2]=a.rangeMax;E[e>>2]=a.precision},ub:(a,b,c)=>{c?35716==b?(a=R.getShaderInfoLog(Qc[a]),null===a&&(a="(unknown error)"),E[c>>2]=a?a.length+1:0):35720==b?(a=R.getShaderSource(Qc[a]),E[c>>2]=a?a.length+1:0):E[c>>2]=R.getShaderParameter(Qc[a],b):S||=1281},tb:rd,sb:sd,rb:(a,b)=>{b=b?cb(B,b):"";if(a=Nc[a]){var c=a,e=c.re,f=c.Oe,k;if(!e){c.re=e={};c.Ne={};var n=R.getProgramParameter(c,35718);for(k=0;k<n;++k){var l=R.getActiveUniform(c,k);var q=
|
||||
l.name;l=l.size;var v=td(q);v=0<v?q.slice(0,v):q;var w=c.Ge;c.Ge+=l;f[v]=[l,w];for(q=0;q<l;++q)e[w]=q,c.Ne[w++]=v}}c=a.re;e=0;f=b;k=td(b);0<k&&(e=parseInt(b.slice(k+1))>>>0,f=b.slice(0,k));if((f=a.Oe[f])&&e<f[0]&&(e+=f[1],c[e]=c[e]||R.getUniformLocation(a,b)))return e}else S||=1281;return-1},qb:(a,b,c)=>{for(var e=jd[b],f=0;f<b;f++)e[f]=E[c+4*f>>2];R.invalidateFramebuffer(a,e)},pb:(a,b,c,e,f,k,n)=>{for(var l=jd[b],q=0;q<b;q++)l[q]=E[c+4*q>>2];R.invalidateSubFramebuffer(a,l,e,f,k,n)},ob:a=>R.isSync(Uc[a]),
|
||||
nb:a=>(a=ka[a])?R.isTexture(a):0,mb:a=>R.lineWidth(a),lb:a=>{a=Nc[a];R.linkProgram(a);a.re=0;a.Oe={}},kb:(a,b,c,e,f,k)=>{R.Le.multiDrawArraysInstancedBaseInstanceWEBGL(a,E,b>>2,E,c>>2,E,e>>2,H,f>>2,k)},jb:(a,b,c,e,f,k,n,l)=>{R.Le.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(a,E,b>>2,c,E,e>>2,E,f>>2,E,k>>2,H,n>>2,l)},ib:(a,b)=>{3317==a?Yc=b:3314==a&&(Zc=b);R.pixelStorei(a,b)},hb:(a,b)=>{R.ge.queryCounterEXT(Sc[a],b)},gb:a=>R.readBuffer(a),fb:(a,b,c,e,f,k,n)=>{if(2<=A.version)if(R.Ce)R.readPixels(a,
|
||||
b,c,e,f,k,n);else{var l=ud(k);n>>>=31-Math.clz32(l.BYTES_PER_ELEMENT);R.readPixels(a,b,c,e,f,k,l,n)}else(l=vd(k,f,c,e,n))?R.readPixels(a,b,c,e,f,k,l):S||=1280},eb:(a,b,c,e)=>R.renderbufferStorage(a,b,c,e),db:(a,b,c,e,f)=>R.renderbufferStorageMultisample(a,b,c,e,f),cb:(a,b,c)=>{R.samplerParameterf(Tc[a],b,c)},bb:(a,b,c)=>{R.samplerParameteri(Tc[a],b,c)},ab:(a,b,c)=>{R.samplerParameteri(Tc[a],b,E[c>>2])},$a:(a,b,c,e)=>R.scissor(a,b,c,e),_a:(a,b,c,e)=>{for(var f="",k=0;k<b;++k){var n=(n=H[c+4*k>>2])?
|
||||
cb(B,n,e?H[e+4*k>>2]:void 0):"";f+=n}R.shaderSource(Qc[a],f)},Za:(a,b,c)=>R.stencilFunc(a,b,c),Ya:(a,b,c,e)=>R.stencilFuncSeparate(a,b,c,e),Xa:a=>R.stencilMask(a),Wa:(a,b)=>R.stencilMaskSeparate(a,b),Va:(a,b,c)=>R.stencilOp(a,b,c),Ua:(a,b,c,e)=>R.stencilOpSeparate(a,b,c,e),Ta:(a,b,c,e,f,k,n,l,q)=>{if(2<=A.version){if(R.le){R.texImage2D(a,b,c,e,f,k,n,l,q);return}if(q){var v=ud(l);q>>>=31-Math.clz32(v.BYTES_PER_ELEMENT);R.texImage2D(a,b,c,e,f,k,n,l,v,q);return}}v=q?vd(l,n,e,f,q):null;R.texImage2D(a,
|
||||
b,c,e,f,k,n,l,v)},Sa:(a,b,c)=>R.texParameterf(a,b,c),Ra:(a,b,c)=>{R.texParameterf(a,b,J[c>>2])},Qa:(a,b,c)=>R.texParameteri(a,b,c),Pa:(a,b,c)=>{R.texParameteri(a,b,E[c>>2])},Oa:(a,b,c,e,f)=>R.texStorage2D(a,b,c,e,f),Na:(a,b,c,e,f,k,n,l,q)=>{if(2<=A.version){if(R.le){R.texSubImage2D(a,b,c,e,f,k,n,l,q);return}if(q){var v=ud(l);R.texSubImage2D(a,b,c,e,f,k,n,l,v,q>>>31-Math.clz32(v.BYTES_PER_ELEMENT));return}}q=q?vd(l,n,f,k,q):null;R.texSubImage2D(a,b,c,e,f,k,n,l,q)},Ma:(a,b)=>{R.uniform1f(V(a),b)},La:(a,
|
||||
b,c)=>{if(2<=A.version)b&&R.uniform1fv(V(a),J,c>>2,b);else{if(288>=b)for(var e=wd[b],f=0;f<b;++f)e[f]=J[c+4*f>>2];else e=J.subarray(c>>2,c+4*b>>2);R.uniform1fv(V(a),e)}},Ka:(a,b)=>{R.uniform1i(V(a),b)},Ja:(a,b,c)=>{if(2<=A.version)b&&R.uniform1iv(V(a),E,c>>2,b);else{if(288>=b)for(var e=xd[b],f=0;f<b;++f)e[f]=E[c+4*f>>2];else e=E.subarray(c>>2,c+4*b>>2);R.uniform1iv(V(a),e)}},Ia:(a,b,c)=>{R.uniform2f(V(a),b,c)},Ha:(a,b,c)=>{if(2<=A.version)b&&R.uniform2fv(V(a),J,c>>2,2*b);else{if(144>=b){b*=2;for(var e=
|
||||
wd[b],f=0;f<b;f+=2)e[f]=J[c+4*f>>2],e[f+1]=J[c+(4*f+4)>>2]}else e=J.subarray(c>>2,c+8*b>>2);R.uniform2fv(V(a),e)}},Ga:(a,b,c)=>{R.uniform2i(V(a),b,c)},Fa:(a,b,c)=>{if(2<=A.version)b&&R.uniform2iv(V(a),E,c>>2,2*b);else{if(144>=b){b*=2;for(var e=xd[b],f=0;f<b;f+=2)e[f]=E[c+4*f>>2],e[f+1]=E[c+(4*f+4)>>2]}else e=E.subarray(c>>2,c+8*b>>2);R.uniform2iv(V(a),e)}},Ea:(a,b,c,e)=>{R.uniform3f(V(a),b,c,e)},Da:(a,b,c)=>{if(2<=A.version)b&&R.uniform3fv(V(a),J,c>>2,3*b);else{if(96>=b){b*=3;for(var e=wd[b],f=0;f<
|
||||
b;f+=3)e[f]=J[c+4*f>>2],e[f+1]=J[c+(4*f+4)>>2],e[f+2]=J[c+(4*f+8)>>2]}else e=J.subarray(c>>2,c+12*b>>2);R.uniform3fv(V(a),e)}},Ca:(a,b,c,e)=>{R.uniform3i(V(a),b,c,e)},Ba:(a,b,c)=>{if(2<=A.version)b&&R.uniform3iv(V(a),E,c>>2,3*b);else{if(96>=b){b*=3;for(var e=xd[b],f=0;f<b;f+=3)e[f]=E[c+4*f>>2],e[f+1]=E[c+(4*f+4)>>2],e[f+2]=E[c+(4*f+8)>>2]}else e=E.subarray(c>>2,c+12*b>>2);R.uniform3iv(V(a),e)}},Aa:(a,b,c,e,f)=>{R.uniform4f(V(a),b,c,e,f)},za:(a,b,c)=>{if(2<=A.version)b&&R.uniform4fv(V(a),J,c>>2,4*
|
||||
b);else{if(72>=b){var e=wd[4*b],f=J;c>>=2;b*=4;for(var k=0;k<b;k+=4){var n=c+k;e[k]=f[n];e[k+1]=f[n+1];e[k+2]=f[n+2];e[k+3]=f[n+3]}}else e=J.subarray(c>>2,c+16*b>>2);R.uniform4fv(V(a),e)}},ya:(a,b,c,e,f)=>{R.uniform4i(V(a),b,c,e,f)},xa:(a,b,c)=>{if(2<=A.version)b&&R.uniform4iv(V(a),E,c>>2,4*b);else{if(72>=b){b*=4;for(var e=xd[b],f=0;f<b;f+=4)e[f]=E[c+4*f>>2],e[f+1]=E[c+(4*f+4)>>2],e[f+2]=E[c+(4*f+8)>>2],e[f+3]=E[c+(4*f+12)>>2]}else e=E.subarray(c>>2,c+16*b>>2);R.uniform4iv(V(a),e)}},wa:(a,b,c,e)=>
|
||||
{if(2<=A.version)b&&R.uniformMatrix2fv(V(a),!!c,J,e>>2,4*b);else{if(72>=b){b*=4;for(var f=wd[b],k=0;k<b;k+=4)f[k]=J[e+4*k>>2],f[k+1]=J[e+(4*k+4)>>2],f[k+2]=J[e+(4*k+8)>>2],f[k+3]=J[e+(4*k+12)>>2]}else f=J.subarray(e>>2,e+16*b>>2);R.uniformMatrix2fv(V(a),!!c,f)}},va:(a,b,c,e)=>{if(2<=A.version)b&&R.uniformMatrix3fv(V(a),!!c,J,e>>2,9*b);else{if(32>=b){b*=9;for(var f=wd[b],k=0;k<b;k+=9)f[k]=J[e+4*k>>2],f[k+1]=J[e+(4*k+4)>>2],f[k+2]=J[e+(4*k+8)>>2],f[k+3]=J[e+(4*k+12)>>2],f[k+4]=J[e+(4*k+16)>>2],f[k+
|
||||
5]=J[e+(4*k+20)>>2],f[k+6]=J[e+(4*k+24)>>2],f[k+7]=J[e+(4*k+28)>>2],f[k+8]=J[e+(4*k+32)>>2]}else f=J.subarray(e>>2,e+36*b>>2);R.uniformMatrix3fv(V(a),!!c,f)}},ua:(a,b,c,e)=>{if(2<=A.version)b&&R.uniformMatrix4fv(V(a),!!c,J,e>>2,16*b);else{if(18>=b){var f=wd[16*b],k=J;e>>=2;b*=16;for(var n=0;n<b;n+=16){var l=e+n;f[n]=k[l];f[n+1]=k[l+1];f[n+2]=k[l+2];f[n+3]=k[l+3];f[n+4]=k[l+4];f[n+5]=k[l+5];f[n+6]=k[l+6];f[n+7]=k[l+7];f[n+8]=k[l+8];f[n+9]=k[l+9];f[n+10]=k[l+10];f[n+11]=k[l+11];f[n+12]=k[l+12];f[n+
|
||||
13]=k[l+13];f[n+14]=k[l+14];f[n+15]=k[l+15]}}else f=J.subarray(e>>2,e+64*b>>2);R.uniformMatrix4fv(V(a),!!c,f)}},ta:a=>{a=Nc[a];R.useProgram(a);R.We=a},sa:(a,b)=>R.vertexAttrib1f(a,b),ra:(a,b)=>{R.vertexAttrib2f(a,J[b>>2],J[b+4>>2])},qa:(a,b)=>{R.vertexAttrib3f(a,J[b>>2],J[b+4>>2],J[b+8>>2])},pa:(a,b)=>{R.vertexAttrib4f(a,J[b>>2],J[b+4>>2],J[b+8>>2],J[b+12>>2])},oa:(a,b)=>{R.vertexAttribDivisor(a,b)},na:(a,b,c,e,f)=>{R.vertexAttribIPointer(a,b,c,e,f)},ma:(a,b,c,e,f,k)=>{R.vertexAttribPointer(a,b,c,
|
||||
!!e,f,k)},la:(a,b,c,e)=>R.viewport(a,b,c,e),ka:(a,b,c,e)=>{R.waitSync(Uc[a],b,(c>>>0)+4294967296*e)},ja:a=>{var b=B.length;a>>>=0;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+1/c);e=Math.min(e,a+100663296);a:{e=(Math.min(2147483648,65536*Math.ceil(Math.max(a,e)/65536))-za.buffer.byteLength+65535)/65536|0;try{za.grow(e);Ha();var f=1;break a}catch(k){}f=void 0}if(f)return!0}return!1},ia:()=>A?A.handle:0,pd:(a,b)=>{var c=0;Ad().forEach((e,f)=>{var k=b+c;f=H[a+4*f>>2]=k;for(k=0;k<e.length;++k)Ca[f++]=
|
||||
e.charCodeAt(k);Ca[f]=0;c+=e.length+1});return 0},od:(a,b)=>{var c=Ad();H[a>>2]=c.length;var e=0;c.forEach(f=>e+=f.length+1);H[b>>2]=e;return 0},ha:a=>{throw new Va(a);},T:()=>52,Z:function(){return 52},nd:()=>52,Y:function(){return 70},S:(a,b,c,e)=>{for(var f=0,k=0;k<c;k++){var n=H[b>>2],l=H[b+4>>2];b+=8;for(var q=0;q<l;q++){var v=B[n+q],w=Bd[a];0===v||10===v?((1===a?wa:ya)(cb(w)),w.length=0):w.push(v)}f+=l}H[e>>2]=f;return 0},ga:cd,fa:ed,ea:fd,da:gd,J:nd,P:rd,ca:sd,k:Hd,u:Id,i:Jd,I:Kd,ba:Ld,O:Md,
|
||||
N:Nd,s:Od,x:Pd,r:Qd,v:Rd,aa:Sd,$:Td,_:Ud},Z=function(){var a={a:Vd};La++;Ra??=r.locateFile?Qa("canvaskit.wasm")?"canvaskit.wasm":ta+"canvaskit.wasm":(new URL("canvaskit.wasm",import.meta.url)).href;Ua(a,function(b){Z=b.instance.exports;za=Z.vd;Ha();O=Z.yd;Ja.unshift(Z.wd);La--;0==La&&(null!==Ma&&(clearInterval(Ma),Ma=null),Oa&&(b=Oa,Oa=null,b()))}).catch(ca);return{}}(),bc=a=>(bc=Z.xd)(a),pd=r._malloc=a=>(pd=r._malloc=Z.zd)(a),cc=r._free=a=>(cc=r._free=Z.Ad)(a),Wd=(a,b)=>(Wd=Z.Bd)(a,b),
|
||||
Xd=a=>(Xd=Z.Cd)(a),Yd=()=>(Yd=Z.Dd)();r.dynCall_viji=(a,b,c,e,f)=>(r.dynCall_viji=Z.Ed)(a,b,c,e,f);r.dynCall_vijiii=(a,b,c,e,f,k,n)=>(r.dynCall_vijiii=Z.Fd)(a,b,c,e,f,k,n);r.dynCall_viiiiij=(a,b,c,e,f,k,n,l)=>(r.dynCall_viiiiij=Z.Gd)(a,b,c,e,f,k,n,l);r.dynCall_jii=(a,b,c)=>(r.dynCall_jii=Z.Hd)(a,b,c);r.dynCall_vij=(a,b,c,e)=>(r.dynCall_vij=Z.Id)(a,b,c,e);r.dynCall_jiiiiii=(a,b,c,e,f,k,n)=>(r.dynCall_jiiiiii=Z.Jd)(a,b,c,e,f,k,n);
|
||||
r.dynCall_jiiiiji=(a,b,c,e,f,k,n,l)=>(r.dynCall_jiiiiji=Z.Kd)(a,b,c,e,f,k,n,l);r.dynCall_ji=(a,b)=>(r.dynCall_ji=Z.Ld)(a,b);r.dynCall_iijj=(a,b,c,e,f,k)=>(r.dynCall_iijj=Z.Md)(a,b,c,e,f,k);r.dynCall_jiji=(a,b,c,e,f)=>(r.dynCall_jiji=Z.Nd)(a,b,c,e,f);r.dynCall_viijii=(a,b,c,e,f,k,n)=>(r.dynCall_viijii=Z.Od)(a,b,c,e,f,k,n);r.dynCall_iiiiij=(a,b,c,e,f,k,n)=>(r.dynCall_iiiiij=Z.Pd)(a,b,c,e,f,k,n);r.dynCall_iiiiijj=(a,b,c,e,f,k,n,l,q)=>(r.dynCall_iiiiijj=Z.Qd)(a,b,c,e,f,k,n,l,q);
|
||||
r.dynCall_iiiiiijj=(a,b,c,e,f,k,n,l,q,v)=>(r.dynCall_iiiiiijj=Z.Rd)(a,b,c,e,f,k,n,l,q,v);function Rd(a,b,c,e,f){var k=Yd();try{O.get(a)(b,c,e,f)}catch(n){Xd(k);if(n!==n+0)throw n;Wd(1,0)}}function Id(a,b,c){var e=Yd();try{return O.get(a)(b,c)}catch(f){Xd(e);if(f!==f+0)throw f;Wd(1,0)}}function Pd(a,b,c){var e=Yd();try{O.get(a)(b,c)}catch(f){Xd(e);if(f!==f+0)throw f;Wd(1,0)}}function Hd(a,b){var c=Yd();try{return O.get(a)(b)}catch(e){Xd(c);if(e!==e+0)throw e;Wd(1,0)}}
|
||||
function Od(a,b){var c=Yd();try{O.get(a)(b)}catch(e){Xd(c);if(e!==e+0)throw e;Wd(1,0)}}function Jd(a,b,c,e){var f=Yd();try{return O.get(a)(b,c,e)}catch(k){Xd(f);if(k!==k+0)throw k;Wd(1,0)}}function Ud(a,b,c,e,f,k,n,l,q,v){var w=Yd();try{O.get(a)(b,c,e,f,k,n,l,q,v)}catch(z){Xd(w);if(z!==z+0)throw z;Wd(1,0)}}function Qd(a,b,c,e){var f=Yd();try{O.get(a)(b,c,e)}catch(k){Xd(f);if(k!==k+0)throw k;Wd(1,0)}}
|
||||
function Td(a,b,c,e,f,k,n){var l=Yd();try{O.get(a)(b,c,e,f,k,n)}catch(q){Xd(l);if(q!==q+0)throw q;Wd(1,0)}}function Md(a,b,c,e,f,k,n,l){var q=Yd();try{return O.get(a)(b,c,e,f,k,n,l)}catch(v){Xd(q);if(v!==v+0)throw v;Wd(1,0)}}function Sd(a,b,c,e,f,k){var n=Yd();try{O.get(a)(b,c,e,f,k)}catch(l){Xd(n);if(l!==l+0)throw l;Wd(1,0)}}function Kd(a,b,c,e,f){var k=Yd();try{return O.get(a)(b,c,e,f)}catch(n){Xd(k);if(n!==n+0)throw n;Wd(1,0)}}
|
||||
function Nd(a,b,c,e,f,k,n,l,q,v){var w=Yd();try{return O.get(a)(b,c,e,f,k,n,l,q,v)}catch(z){Xd(w);if(z!==z+0)throw z;Wd(1,0)}}function Ld(a,b,c,e,f,k,n){var l=Yd();try{return O.get(a)(b,c,e,f,k,n)}catch(q){Xd(l);if(q!==q+0)throw q;Wd(1,0)}}var Zd,$d;Oa=function ae(){Zd||be();Zd||(Oa=ae)};function be(){if(!(0<La)){if(!$d&&($d=1,Wa(Ia),0<La))return;Zd||(Zd=1,r.calledRun=1,Aa||(Wa(Ja),aa(r),r.onRuntimeInitialized?.(),Wa(Ka)))}}be();moduleRtn=da;
|
||||
|
||||
|
||||
return moduleRtn;
|
||||
}
|
||||
);
|
||||
})();
|
||||
export default CanvasKitInit;
|
||||
158
internal/form_generator/templates/canvaskit/skwasm.js
Normal file
@@ -0,0 +1,158 @@
|
||||
|
||||
var skwasm = (() => {
|
||||
var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined;
|
||||
|
||||
return (
|
||||
function(moduleArg = {}) {
|
||||
var moduleRtn;
|
||||
|
||||
function aa(){e.buffer!=h.buffer&&k();return h}function n(){e.buffer!=h.buffer&&k();return ba}function q(){e.buffer!=h.buffer&&k();return ca}function t(){e.buffer!=h.buffer&&k();return da}function u(){e.buffer!=h.buffer&&k();return ea}function fa(){e.buffer!=h.buffer&&k();return ha}var v=moduleArg,ia,ja,ka=new Promise((a,b)=>{ia=a;ja=b}),la="object"==typeof window,ma="function"==typeof importScripts,w=ma&&self.name?.startsWith("em-pthread"),na=Object.assign({},v),x="",oa,pa;
|
||||
if(la||ma)ma?x=self.location.href:"undefined"!=typeof document&&document.currentScript&&(x=document.currentScript.src),_scriptName&&(x=_scriptName),x.startsWith("blob:")?x="":x=x.substr(0,x.replace(/[?#].*/,"").lastIndexOf("/")+1),ma&&(pa=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),oa=a=>fetch(a,{credentials:"same-origin"}).then(b=>b.ok?b.arrayBuffer():Promise.reject(Error(b.status+" : "+b.url)));
|
||||
var qa=console.log.bind(console),y=console.error.bind(console);Object.assign(v,na);na=null;var e,ra,sa=!1,ta,h,ba,ua,va,ca,da,ea,ha;function k(){var a=e.buffer;h=new Int8Array(a);ua=new Int16Array(a);ba=new Uint8Array(a);va=new Uint16Array(a);ca=new Int32Array(a);da=new Uint32Array(a);ea=new Float32Array(a);ha=new Float64Array(a)}
|
||||
if(w){var wa,xa=!1;y=function(...b){console.error(b.join(" "))};self.alert=function(...b){postMessage({g:"alert",text:b.join(" "),na:ya()})};v.instantiateWasm=(b,c)=>new Promise(d=>{wa=f=>{f=new WebAssembly.Instance(f,za());c(f);d()}});self.onunhandledrejection=b=>{throw b.reason||b;};function a(b){try{var c=b.data,d=c.g;if("load"===d){let f=[];self.onmessage=g=>f.push(g);self.startWorker=()=>{postMessage({g:"loaded"});for(let g of f)a(g);self.onmessage=a};for(const g of c.ca)if(!v[g]||v[g].proxy)v[g]=
|
||||
(...l)=>{postMessage({g:"callHandler",ba:g,X:l})},"print"==g&&(qa=v[g]),"printErr"==g&&(y=v[g]);e=c.pa;k();wa(c.qa)}else if("run"===d){Aa(c.l);Ba(c.l,0,0,1,0,0);Ca(c);Da();Ea(c.l);xa||=!0;try{Fa(c.la,c.J)}catch(f){if("unwind"!=f)throw f;}}else"setimmediate"!==c.target&&("checkMailbox"===d?xa&&Ga():d&&(y(`worker: received unknown command ${d}`),y(c)))}catch(f){throw Ha(),f;}}self.onmessage=a}w||(e=new WebAssembly.Memory({initial:256,maximum:32768,shared:!0}),k());
|
||||
var Ia=[],Ja=[],Ka=[],z=0,La=null,Ma=null;function Na(){z--;if(0==z&&(null!==La&&(clearInterval(La),La=null),Ma)){var a=Ma;Ma=null;a()}}function Oa(a){a="Aborted("+a+")";y(a);sa=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");ja(a);throw a;}var Pa=a=>a.startsWith("data:application/octet-stream;base64,"),Qa;function Ra(a){return oa(a).then(b=>new Uint8Array(b),()=>{if(pa)var b=pa(a);else throw"both async and sync fetching of the wasm failed";return b})}
|
||||
function Sa(a,b,c){return Ra(a).then(d=>WebAssembly.instantiate(d,b)).then(c,d=>{y(`failed to asynchronously prepare wasm: ${d}`);Oa(d)})}function Ta(a,b){var c=Qa;return"function"!=typeof WebAssembly.instantiateStreaming||Pa(c)||"function"!=typeof fetch?Sa(c,a,b):fetch(c,{credentials:"same-origin"}).then(d=>WebAssembly.instantiateStreaming(d,a).then(b,function(f){y(`wasm streaming compile failed: ${f}`);y("falling back to ArrayBuffer instantiation");return Sa(c,a,b)}))}
|
||||
function za(){Ua={__cxa_throw:Va,__pthread_create_js:Wa,__syscall_fcntl64:Xa,__syscall_fstat64:Ya,__syscall_ioctl:Za,__syscall_openat:$a,_abort_js:ab,_emscripten_get_now_is_monotonic:bb,_emscripten_init_main_thread_js:cb,_emscripten_notify_mailbox_postmessage:db,_emscripten_receive_on_main_thread_js:eb,_emscripten_runtime_keepalive_clear:fb,_emscripten_thread_cleanup:gb,_emscripten_thread_mailbox_await:Ea,_emscripten_thread_set_strongref:hb,_emscripten_throw_longjmp:ib,_mmap_js:jb,_munmap_js:kb,_setitimer_js:lb,
|
||||
_tzset_js:mb,emscripten_check_blocking_allowed:nb,emscripten_exit_with_live_runtime:ob,emscripten_get_now:pb,emscripten_glActiveTexture:qb,emscripten_glAttachShader:rb,emscripten_glBeginQuery:sb,emscripten_glBeginQueryEXT:tb,emscripten_glBindAttribLocation:ub,emscripten_glBindBuffer:vb,emscripten_glBindFramebuffer:wb,emscripten_glBindRenderbuffer:xb,emscripten_glBindSampler:yb,emscripten_glBindTexture:zb,emscripten_glBindVertexArray:Ab,emscripten_glBindVertexArrayOES:Ab,emscripten_glBlendColor:Bb,
|
||||
emscripten_glBlendEquation:Cb,emscripten_glBlendFunc:Db,emscripten_glBlitFramebuffer:Eb,emscripten_glBufferData:Fb,emscripten_glBufferSubData:Gb,emscripten_glCheckFramebufferStatus:Hb,emscripten_glClear:Ib,emscripten_glClearColor:Jb,emscripten_glClearStencil:Kb,emscripten_glClientWaitSync:Lb,emscripten_glColorMask:Mb,emscripten_glCompileShader:Nb,emscripten_glCompressedTexImage2D:Ob,emscripten_glCompressedTexSubImage2D:Pb,emscripten_glCopyBufferSubData:Qb,emscripten_glCopyTexSubImage2D:Rb,emscripten_glCreateProgram:Sb,
|
||||
emscripten_glCreateShader:Tb,emscripten_glCullFace:Ub,emscripten_glDeleteBuffers:Vb,emscripten_glDeleteFramebuffers:Wb,emscripten_glDeleteProgram:Xb,emscripten_glDeleteQueries:Yb,emscripten_glDeleteQueriesEXT:Zb,emscripten_glDeleteRenderbuffers:$b,emscripten_glDeleteSamplers:ac,emscripten_glDeleteShader:bc,emscripten_glDeleteSync:cc,emscripten_glDeleteTextures:dc,emscripten_glDeleteVertexArrays:ec,emscripten_glDeleteVertexArraysOES:ec,emscripten_glDepthMask:fc,emscripten_glDisable:gc,emscripten_glDisableVertexAttribArray:hc,
|
||||
emscripten_glDrawArrays:ic,emscripten_glDrawArraysInstanced:jc,emscripten_glDrawArraysInstancedBaseInstanceWEBGL:kc,emscripten_glDrawBuffers:lc,emscripten_glDrawElements:mc,emscripten_glDrawElementsInstanced:nc,emscripten_glDrawElementsInstancedBaseVertexBaseInstanceWEBGL:oc,emscripten_glDrawRangeElements:pc,emscripten_glEnable:qc,emscripten_glEnableVertexAttribArray:rc,emscripten_glEndQuery:sc,emscripten_glEndQueryEXT:tc,emscripten_glFenceSync:uc,emscripten_glFinish:vc,emscripten_glFlush:wc,emscripten_glFramebufferRenderbuffer:xc,
|
||||
emscripten_glFramebufferTexture2D:yc,emscripten_glFrontFace:zc,emscripten_glGenBuffers:Ac,emscripten_glGenFramebuffers:Bc,emscripten_glGenQueries:Cc,emscripten_glGenQueriesEXT:Dc,emscripten_glGenRenderbuffers:Ec,emscripten_glGenSamplers:Fc,emscripten_glGenTextures:Gc,emscripten_glGenVertexArrays:Hc,emscripten_glGenVertexArraysOES:Hc,emscripten_glGenerateMipmap:Ic,emscripten_glGetBufferParameteriv:Jc,emscripten_glGetError:Kc,emscripten_glGetFloatv:Lc,emscripten_glGetFramebufferAttachmentParameteriv:Mc,
|
||||
emscripten_glGetIntegerv:Nc,emscripten_glGetProgramInfoLog:Oc,emscripten_glGetProgramiv:Pc,emscripten_glGetQueryObjecti64vEXT:Qc,emscripten_glGetQueryObjectui64vEXT:Qc,emscripten_glGetQueryObjectuiv:Rc,emscripten_glGetQueryObjectuivEXT:Sc,emscripten_glGetQueryiv:Tc,emscripten_glGetQueryivEXT:Uc,emscripten_glGetRenderbufferParameteriv:Vc,emscripten_glGetShaderInfoLog:Wc,emscripten_glGetShaderPrecisionFormat:Xc,emscripten_glGetShaderiv:Yc,emscripten_glGetString:Zc,emscripten_glGetStringi:$c,emscripten_glGetUniformLocation:ad,
|
||||
emscripten_glInvalidateFramebuffer:bd,emscripten_glInvalidateSubFramebuffer:cd,emscripten_glIsSync:dd,emscripten_glIsTexture:ed,emscripten_glLineWidth:fd,emscripten_glLinkProgram:gd,emscripten_glMultiDrawArraysInstancedBaseInstanceWEBGL:hd,emscripten_glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL:jd,emscripten_glPixelStorei:kd,emscripten_glQueryCounterEXT:ld,emscripten_glReadBuffer:md,emscripten_glReadPixels:nd,emscripten_glRenderbufferStorage:od,emscripten_glRenderbufferStorageMultisample:pd,
|
||||
emscripten_glSamplerParameterf:qd,emscripten_glSamplerParameteri:rd,emscripten_glSamplerParameteriv:sd,emscripten_glScissor:td,emscripten_glShaderSource:ud,emscripten_glStencilFunc:vd,emscripten_glStencilFuncSeparate:wd,emscripten_glStencilMask:xd,emscripten_glStencilMaskSeparate:yd,emscripten_glStencilOp:zd,emscripten_glStencilOpSeparate:Ad,emscripten_glTexImage2D:Bd,emscripten_glTexParameterf:Cd,emscripten_glTexParameterfv:Dd,emscripten_glTexParameteri:Ed,emscripten_glTexParameteriv:Fd,emscripten_glTexStorage2D:Gd,
|
||||
emscripten_glTexSubImage2D:Hd,emscripten_glUniform1f:Id,emscripten_glUniform1fv:Jd,emscripten_glUniform1i:Kd,emscripten_glUniform1iv:Ld,emscripten_glUniform2f:Md,emscripten_glUniform2fv:Nd,emscripten_glUniform2i:Od,emscripten_glUniform2iv:Pd,emscripten_glUniform3f:Qd,emscripten_glUniform3fv:Rd,emscripten_glUniform3i:Sd,emscripten_glUniform3iv:Td,emscripten_glUniform4f:Ud,emscripten_glUniform4fv:Vd,emscripten_glUniform4i:Wd,emscripten_glUniform4iv:Xd,emscripten_glUniformMatrix2fv:Yd,emscripten_glUniformMatrix3fv:Zd,
|
||||
emscripten_glUniformMatrix4fv:$d,emscripten_glUseProgram:ae,emscripten_glVertexAttrib1f:be,emscripten_glVertexAttrib2fv:ce,emscripten_glVertexAttrib3fv:de,emscripten_glVertexAttrib4fv:ee,emscripten_glVertexAttribDivisor:fe,emscripten_glVertexAttribIPointer:ge,emscripten_glVertexAttribPointer:he,emscripten_glViewport:ie,emscripten_glWaitSync:je,emscripten_resize_heap:ke,emscripten_webgl_enable_extension:le,emscripten_webgl_get_current_context:me,emscripten_webgl_make_context_current:ne,environ_get:oe,
|
||||
environ_sizes_get:pe,exit:qe,fd_close:re,fd_pread:se,fd_read:te,fd_seek:ue,fd_write:ve,glDeleteTextures:dc,glGetIntegerv:Nc,glGetString:Zc,glGetStringi:$c,invoke_ii:we,invoke_iii:xe,invoke_iiii:ye,invoke_iiiii:ze,invoke_iiiiiii:Ae,invoke_vi:Be,invoke_vii:Ce,invoke_viii:De,invoke_viiii:Ee,invoke_viiiiiii:Fe,memory:e,proc_exit:Ge,skwasm_captureImageBitmap:He,skwasm_connectThread:Ie,skwasm_createGlTextureFromTextureSource:Je,skwasm_createOffscreenCanvas:Ke,skwasm_dispatchDisposeSurface:Le,skwasm_dispatchRasterizeImage:Me,
|
||||
skwasm_dispatchRenderPictures:Ne,skwasm_disposeAssociatedObjectOnThread:Oe,skwasm_getAssociatedObject:Pe,skwasm_postRasterizeResult:Qe,skwasm_resizeCanvas:Re,skwasm_resolveAndPostImages:Se,skwasm_setAssociatedObjectOnThread:Te};return{env:Ua,wasi_snapshot_preview1:Ua}}function Ue(a){this.name="ExitStatus";this.message=`Program terminated with exit(${a})`;this.status=a}
|
||||
var Ve=a=>{a.terminate();a.onmessage=()=>{}},Ze=a=>{0==A.length&&(We(),Xe(A[0]));var b=A.pop();if(!b)return 6;Ye.push(b);B[a.l]=b;b.l=a.l;var c={g:"run",la:a.ka,J:a.J,l:a.l};c.B=a.B;c.L=a.L;b.postMessage(c,a.U);return 0},D=0,af=a=>$e(a);v.stackAlloc=af;var H=(a,b,...c)=>{for(var d=c.length,f=E(),g=$e(8*d),l=g>>3,m=0;m<c.length;m++){var p=c[m];fa()[l+m]=p}a=bf(a,0,d,g,b);G(f);return a};
|
||||
function Ge(a){if(w)return H(0,1,a);ta=a;if(!(cf||0<D)){for(var b of Ye)Ve(b);for(b of A)Ve(b);A=[];Ye=[];B=[];sa=!0}throw new Ue(a);}var df=a=>{if(!(a instanceof Ue||"unwind"==a))throw a;};function ef(a){if(w)return H(1,0,a);qe(a)}var qe=a=>{ta=a;if(w)throw ef(a),"unwind";Ge(a)},A=[],Ye=[],ff=[],B={};function gf(){for(var a=1;a--;)We();Ia.unshift(()=>{z++;hf(()=>Na())})}var kf=a=>{var b=a.l;delete B[b];A.push(a);Ye.splice(Ye.indexOf(a),1);a.l=0;jf(b)};
|
||||
function Ca(a){"undefined"!=typeof lf&&(Object.assign(mf,a.L),!v.canvas&&a.B&&mf[a.B]&&(v.canvas=mf[a.B].T,v.canvas.id=a.B))}function Da(){ff.forEach(a=>a())}
|
||||
var Xe=a=>new Promise(b=>{a.onmessage=g=>{g=g.data;var l=g.g;if(g.I&&g.I!=ya()){var m=B[g.I];m?m.postMessage(g,g.U):y(`Internal error! Worker sent a message "${l}" to target pthread ${g.I}, but that thread no longer exists!`)}else if("checkMailbox"===l)Ga();else if("spawnThread"===l)Ze(g);else if("cleanupThread"===l)kf(B[g.ma]);else if("loaded"===l)a.loaded=!0,b(a);else if("alert"===l)alert(`Thread ${g.na}: ${g.text}`);else if("setimmediate"===g.target)a.postMessage(g);else if("callHandler"===l)v[g.ba](...g.X);
|
||||
else l&&y(`worker sent an unknown command ${l}`)};a.onerror=g=>{y(`${"worker sent an error!"} ${g.filename}:${g.lineno}: ${g.message}`);throw g;};var c=[],d=[],f;for(f of d)v.propertyIsEnumerable(f)&&c.push(f);a.postMessage({g:"load",ca:c,pa:e,qa:ra})});function hf(a){w?a():Promise.all(A.map(Xe)).then(a)}function We(){var a=_scriptName;v.mainScriptUrlOrBlob&&(a=v.mainScriptUrlOrBlob,"string"!=typeof a&&(a=URL.createObjectURL(a)));a=new Worker(a,{type:"module",name:"em-pthread"});A.push(a)}
|
||||
var nf=a=>{a.forEach(b=>b(v))},Aa=a=>{k();var b=t()[a+52>>2];a=t()[a+56>>2];of(b,b-a);G(b)},I,Fa=(a,b)=>{cf=D=0;a=I.get(a)(b);cf||0<D?ta=a:pf(a)},cf=v.noExitRuntime||!0;class qf{constructor(a){this.A=a-24}}var rf=0,sf=0,Va=(a,b,c)=>{var d=new qf(a);t()[d.A+16>>2]=0;t()[d.A+4>>2]=b;t()[d.A+8>>2]=c;rf=a;sf++;throw rf;};function tf(a,b,c,d){return w?H(2,1,a,b,c,d):Wa(a,b,c,d)}
|
||||
var uf="undefined"!=typeof TextDecoder?new TextDecoder:void 0,vf=(a,b=0,c=NaN)=>{var d=b+c;for(c=b;a[c]&&!(c>=d);)++c;if(16<c-b&&a.buffer&&uf)return uf.decode(a.slice(b,c));for(d="";b<c;){var f=a[b++];if(f&128){var g=a[b++]&63;if(192==(f&224))d+=String.fromCharCode((f&31)<<6|g);else{var l=a[b++]&63;f=224==(f&240)?(f&15)<<12|g<<6|l:(f&7)<<18|g<<12|l<<6|a[b++]&63;65536>f?d+=String.fromCharCode(f):(f-=65536,d+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else d+=String.fromCharCode(f)}return d},wf=
|
||||
(a,b)=>a?vf(n(),a,b):"",Wa=(a,b,c,d)=>{if("undefined"==typeof SharedArrayBuffer)return 6;var f=[],g=0,l=b?t()[b+40>>2]:0;l=(l=4294967295==l?"#canvas":wf(l).trim())?l.split(","):[];var m={},p=v.canvas?.id||"";for(r of l){var r=r.trim();try{if("#canvas"==r){if(!v.canvas){y(`pthread_create: could not find canvas with ID "${r}" to transfer to thread!`);g=28;break}r=v.canvas.id}if(mf[r]){var F=mf[r];mf[r]=null;v.canvas instanceof OffscreenCanvas&&r===v.canvas.id&&(v.canvas=null)}else if(!w){var C=v.canvas&&
|
||||
v.canvas.id===r?v.canvas:document.querySelector(r);if(!C){y(`pthread_create: could not find canvas with ID "${r}" to transfer to thread!`);g=28;break}if(C.Y){y(`pthread_create: cannot transfer canvas with ID "${r}" to thread, since the current thread does not have control over it!`);g=63;break}if(C.transferControlToOffscreen)C.u||(C.u=xf(12),q()[C.u>>2]=C.width,q()[C.u+4>>2]=C.height,t()[C.u+8>>2]=0),F={T:C.transferControlToOffscreen(),u:C.u,id:C.id},C.Y=!0;else return y(`pthread_create: cannot transfer control of canvas "${r}" to pthread, because current browser does not support OffscreenCanvas!`),
|
||||
y("pthread_create: Build with -sOFFSCREEN_FRAMEBUFFER to enable fallback proxying of GL commands from pthread to main thread."),52}F&&(f.push(F.T),m[F.id]=F)}catch(rg){return y(`pthread_create: failed to transfer control of canvas "${r}" to OffscreenCanvas! Error: ${rg}`),28}}if(w&&(0===f.length||g))return tf(a,b,c,d);if(g)return g;for(C of Object.values(m))t()[C.u+8>>2]=a;a={ka:c,l:a,J:d,B:p,L:m,U:f};return w?(a.g="spawnThread",postMessage(a,f),0):Ze(a)};
|
||||
function Xa(a,b,c){return w?H(3,1,a,b,c):0}function Ya(a,b){if(w)return H(4,1,a,b)}function Za(a,b,c){return w?H(5,1,a,b,c):0}function $a(a,b,c,d){if(w)return H(6,1,a,b,c,d)}
|
||||
var ab=()=>{Oa("")},bb=()=>1,cb=a=>{Ba(a,!ma,1,!la,65536,!1);Da()},yf=a=>{if(!sa)try{if(a(),!(cf||0<D))try{w?pf(ta):qe(ta)}catch(b){df(b)}}catch(b){df(b)}},Ea=a=>{"function"===typeof Atomics.oa&&(Atomics.oa(q(),a>>2,a).value.then(Ga),a+=128,Atomics.store(q(),a>>2,1))},Ga=()=>{var a=ya();a&&(Ea(a),yf(zf))},db=(a,b)=>{a==b?setTimeout(Ga):w?postMessage({I:a,g:"checkMailbox"}):(a=B[a])&&a.postMessage({g:"checkMailbox"})},Af=[],eb=(a,b,c,d,f)=>{Af.length=d;b=f>>3;for(c=0;c<d;c++)Af[c]=fa()[b+c];return(0,Bf[a])(...Af)},
|
||||
fb=()=>{cf=!1;D=0},gb=a=>{w?postMessage({g:"cleanupThread",ma:a}):kf(B[a])},hb=()=>{},ib=()=>{throw Infinity;};function jb(a,b,c,d,f,g,l,m){return w?H(7,1,a,b,c,d,f,g,l,m):-52}function kb(a,b,c,d,f,g,l){if(w)return H(8,1,a,b,c,d,f,g,l)}var Cf={},pb=()=>performance.timeOrigin+performance.now();
|
||||
function lb(a,b){if(w)return H(9,1,a,b);Cf[a]&&(clearTimeout(Cf[a].id),delete Cf[a]);if(!b)return 0;var c=setTimeout(()=>{delete Cf[a];yf(()=>Df(a,performance.timeOrigin+performance.now()))},b);Cf[a]={id:c,ua:b};return 0}
|
||||
var J=(a,b,c)=>{var d=n();if(0<c){var f=b;c=b+c-1;for(var g=0;g<a.length;++g){var l=a.charCodeAt(g);if(55296<=l&&57343>=l){var m=a.charCodeAt(++g);l=65536+((l&1023)<<10)|m&1023}if(127>=l){if(b>=c)break;d[b++]=l}else{if(2047>=l){if(b+1>=c)break;d[b++]=192|l>>6}else{if(65535>=l){if(b+2>=c)break;d[b++]=224|l>>12}else{if(b+3>=c)break;d[b++]=240|l>>18;d[b++]=128|l>>12&63}d[b++]=128|l>>6&63}d[b++]=128|l&63}}d[b]=0;a=b-f}else a=0;return a},mb=(a,b,c,d)=>{var f=(new Date).getFullYear(),g=(new Date(f,0,1)).getTimezoneOffset();
|
||||
f=(new Date(f,6,1)).getTimezoneOffset();var l=Math.max(g,f);t()[a>>2]=60*l;q()[b>>2]=Number(g!=f);b=m=>{var p=Math.abs(m);return`UTC${0<=m?"-":"+"}${String(Math.floor(p/60)).padStart(2,"0")}${String(p%60).padStart(2,"0")}`};a=b(g);b=b(f);f<g?(J(a,c,17),J(b,d,17)):(J(a,d,17),J(b,c,17))},nb=()=>{},ob=()=>{D+=1;throw"unwind";},K,Ef=a=>{var b=a.getExtension("ANGLE_instanced_arrays");b&&(a.vertexAttribDivisor=(c,d)=>b.vertexAttribDivisorANGLE(c,d),a.drawArraysInstanced=(c,d,f,g)=>b.drawArraysInstancedANGLE(c,
|
||||
d,f,g),a.drawElementsInstanced=(c,d,f,g,l)=>b.drawElementsInstancedANGLE(c,d,f,g,l))},Ff=a=>{var b=a.getExtension("OES_vertex_array_object");b&&(a.createVertexArray=()=>b.createVertexArrayOES(),a.deleteVertexArray=c=>b.deleteVertexArrayOES(c),a.bindVertexArray=c=>b.bindVertexArrayOES(c),a.isVertexArray=c=>b.isVertexArrayOES(c))},Gf=a=>{var b=a.getExtension("WEBGL_draw_buffers");b&&(a.drawBuffers=(c,d)=>b.drawBuffersWEBGL(c,d))},Hf=a=>{a.O=a.getExtension("WEBGL_draw_instanced_base_vertex_base_instance")},
|
||||
If=a=>{a.S=a.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance")},Jf=a=>{var b="ANGLE_instanced_arrays EXT_blend_minmax EXT_disjoint_timer_query EXT_frag_depth EXT_shader_texture_lod EXT_sRGB OES_element_index_uint OES_fbo_render_mipmap OES_standard_derivatives OES_texture_float OES_texture_half_float OES_texture_half_float_linear OES_vertex_array_object WEBGL_color_buffer_float WEBGL_depth_texture WEBGL_draw_buffers EXT_color_buffer_float EXT_conservative_depth EXT_disjoint_timer_query_webgl2 EXT_texture_norm16 NV_shader_noperspective_interpolation WEBGL_clip_cull_distance EXT_clip_control EXT_color_buffer_half_float EXT_depth_clamp EXT_float_blend EXT_polygon_offset_clamp EXT_texture_compression_bptc EXT_texture_compression_rgtc EXT_texture_filter_anisotropic KHR_parallel_shader_compile OES_texture_float_linear WEBGL_blend_func_extended WEBGL_compressed_texture_astc WEBGL_compressed_texture_etc WEBGL_compressed_texture_etc1 WEBGL_compressed_texture_s3tc WEBGL_compressed_texture_s3tc_srgb WEBGL_debug_renderer_info WEBGL_debug_shaders WEBGL_lose_context WEBGL_multi_draw WEBGL_polygon_mode".split(" ");
|
||||
return(a.getSupportedExtensions()||[]).filter(c=>b.includes(c))},Kf=1,Lf=[],L=[],Mf=[],Nf=[],M=[],N=[],Of=[],Pf={},mf={},O=[],P=[],Q=[],Qf={},Rf={},Sf=4,Tf=0,Uf=a=>{for(var b=Kf++,c=a.length;c<b;c++)a[c]=null;return b},S=(a,b,c,d)=>{for(var f=0;f<a;f++){var g=K[c](),l=g&&Uf(d);g?(g.name=l,d[l]=g):R||=1282;q()[b+4*f>>2]=l}},Wf=a=>{var b={R:2,alpha:!0,depth:!0,stencil:!0,antialias:!1,premultipliedAlpha:!0,preserveDrawingBuffer:!1,powerPreference:"default",failIfMajorPerformanceCaveat:!1,P:!0};a.A||
|
||||
(a.A=a.getContext,a.getContext=function(d,f){f=a.A(d,f);return"webgl"==d==f instanceof WebGLRenderingContext?f:null});var c=1<b.R?a.getContext("webgl2",b):a.getContext("webgl",b);return c?Vf(c,b):0},Vf=(a,b)=>{var c=xf(8);t()[c+4>>2]=ya();var d={handle:c,attributes:b,version:b.R,D:a};a.canvas&&(a.canvas.sa=d);Pf[c]=d;("undefined"==typeof b.P||b.P)&&Xf(d);return c},Xf=a=>{a||=T;if(!a.ea){a.ea=!0;var b=a.D;b.fa=b.getExtension("WEBGL_multi_draw");b.aa=b.getExtension("EXT_polygon_offset_clamp");b.$=b.getExtension("EXT_clip_control");
|
||||
b.ra=b.getExtension("WEBGL_polygon_mode");Ef(b);Ff(b);Gf(b);Hf(b);If(b);2<=a.version&&(b.h=b.getExtension("EXT_disjoint_timer_query_webgl2"));if(2>a.version||!b.h)b.h=b.getExtension("EXT_disjoint_timer_query");Jf(b).forEach(c=>{c.includes("lose_context")||c.includes("debug")||b.getExtension(c)})}},lf={},R,T,qb=a=>K.activeTexture(a),rb=(a,b)=>{K.attachShader(L[a],N[b])},sb=(a,b)=>{K.beginQuery(a,O[b])},tb=(a,b)=>{K.h.beginQueryEXT(a,O[b])},ub=(a,b,c)=>{K.bindAttribLocation(L[a],b,wf(c))},vb=(a,b)=>
|
||||
{35051==a?K.K=b:35052==a&&(K.v=b);K.bindBuffer(a,Lf[b])},wb=(a,b)=>{K.bindFramebuffer(a,Mf[b])},xb=(a,b)=>{K.bindRenderbuffer(a,Nf[b])},yb=(a,b)=>{K.bindSampler(a,P[b])},zb=(a,b)=>{K.bindTexture(a,M[b])},Ab=a=>{K.bindVertexArray(Of[a])},Bb=(a,b,c,d)=>K.blendColor(a,b,c,d),Cb=a=>K.blendEquation(a),Db=(a,b)=>K.blendFunc(a,b),Eb=(a,b,c,d,f,g,l,m,p,r)=>K.blitFramebuffer(a,b,c,d,f,g,l,m,p,r),Fb=(a,b,c,d)=>{2<=T.version?c&&b?K.bufferData(a,n(),d,c,b):K.bufferData(a,b,d):K.bufferData(a,c?n().subarray(c,
|
||||
c+b):b,d)},Gb=(a,b,c,d)=>{2<=T.version?c&&K.bufferSubData(a,b,n(),d,c):K.bufferSubData(a,b,n().subarray(d,d+c))},Hb=a=>K.checkFramebufferStatus(a),Ib=a=>K.clear(a),Jb=(a,b,c,d)=>K.clearColor(a,b,c,d),Kb=a=>K.clearStencil(a),Lb=(a,b,c,d)=>K.clientWaitSync(Q[a],b,(c>>>0)+4294967296*d),Mb=(a,b,c,d)=>{K.colorMask(!!a,!!b,!!c,!!d)},Nb=a=>{K.compileShader(N[a])},Ob=(a,b,c,d,f,g,l,m)=>{2<=T.version?K.v||!l?K.compressedTexImage2D(a,b,c,d,f,g,l,m):K.compressedTexImage2D(a,b,c,d,f,g,n(),m,l):K.compressedTexImage2D(a,
|
||||
b,c,d,f,g,n().subarray(m,m+l))},Pb=(a,b,c,d,f,g,l,m,p)=>{2<=T.version?K.v||!m?K.compressedTexSubImage2D(a,b,c,d,f,g,l,m,p):K.compressedTexSubImage2D(a,b,c,d,f,g,l,n(),p,m):K.compressedTexSubImage2D(a,b,c,d,f,g,l,n().subarray(p,p+m))},Qb=(a,b,c,d,f)=>K.copyBufferSubData(a,b,c,d,f),Rb=(a,b,c,d,f,g,l,m)=>K.copyTexSubImage2D(a,b,c,d,f,g,l,m),Sb=()=>{var a=Uf(L),b=K.createProgram();b.name=a;b.H=b.F=b.G=0;b.N=1;L[a]=b;return a},Tb=a=>{var b=Uf(N);N[b]=K.createShader(a);return b},Ub=a=>K.cullFace(a),Vb=
|
||||
(a,b)=>{for(var c=0;c<a;c++){var d=q()[b+4*c>>2],f=Lf[d];f&&(K.deleteBuffer(f),f.name=0,Lf[d]=null,d==K.K&&(K.K=0),d==K.v&&(K.v=0))}},Wb=(a,b)=>{for(var c=0;c<a;++c){var d=q()[b+4*c>>2],f=Mf[d];f&&(K.deleteFramebuffer(f),f.name=0,Mf[d]=null)}},Xb=a=>{if(a){var b=L[a];b?(K.deleteProgram(b),b.name=0,L[a]=null):R||=1281}},Yb=(a,b)=>{for(var c=0;c<a;c++){var d=q()[b+4*c>>2],f=O[d];f&&(K.deleteQuery(f),O[d]=null)}},Zb=(a,b)=>{for(var c=0;c<a;c++){var d=q()[b+4*c>>2],f=O[d];f&&(K.h.deleteQueryEXT(f),O[d]=
|
||||
null)}},$b=(a,b)=>{for(var c=0;c<a;c++){var d=q()[b+4*c>>2],f=Nf[d];f&&(K.deleteRenderbuffer(f),f.name=0,Nf[d]=null)}},ac=(a,b)=>{for(var c=0;c<a;c++){var d=q()[b+4*c>>2],f=P[d];f&&(K.deleteSampler(f),f.name=0,P[d]=null)}},bc=a=>{if(a){var b=N[a];b?(K.deleteShader(b),N[a]=null):R||=1281}},cc=a=>{if(a){var b=Q[a];b?(K.deleteSync(b),b.name=0,Q[a]=null):R||=1281}},dc=(a,b)=>{for(var c=0;c<a;c++){var d=q()[b+4*c>>2],f=M[d];f&&(K.deleteTexture(f),f.name=0,M[d]=null)}},ec=(a,b)=>{for(var c=0;c<a;c++){var d=
|
||||
q()[b+4*c>>2];K.deleteVertexArray(Of[d]);Of[d]=null}},fc=a=>{K.depthMask(!!a)},gc=a=>K.disable(a),hc=a=>{K.disableVertexAttribArray(a)},ic=(a,b,c)=>{K.drawArrays(a,b,c)},jc=(a,b,c,d)=>{K.drawArraysInstanced(a,b,c,d)},kc=(a,b,c,d,f)=>{K.O.drawArraysInstancedBaseInstanceWEBGL(a,b,c,d,f)},Yf=[],lc=(a,b)=>{for(var c=Yf[a],d=0;d<a;d++)c[d]=q()[b+4*d>>2];K.drawBuffers(c)},mc=(a,b,c,d)=>{K.drawElements(a,b,c,d)},nc=(a,b,c,d,f)=>{K.drawElementsInstanced(a,b,c,d,f)},oc=(a,b,c,d,f,g,l)=>{K.O.drawElementsInstancedBaseVertexBaseInstanceWEBGL(a,
|
||||
b,c,d,f,g,l)},pc=(a,b,c,d,f,g)=>{K.drawElements(a,d,f,g)},qc=a=>K.enable(a),rc=a=>{K.enableVertexAttribArray(a)},sc=a=>K.endQuery(a),tc=a=>{K.h.endQueryEXT(a)},uc=(a,b)=>(a=K.fenceSync(a,b))?(b=Uf(Q),a.name=b,Q[b]=a,b):0,vc=()=>K.finish(),wc=()=>K.flush(),xc=(a,b,c,d)=>{K.framebufferRenderbuffer(a,b,c,Nf[d])},yc=(a,b,c,d,f)=>{K.framebufferTexture2D(a,b,c,M[d],f)},zc=a=>K.frontFace(a),Ac=(a,b)=>{S(a,b,"createBuffer",Lf)},Bc=(a,b)=>{S(a,b,"createFramebuffer",Mf)},Cc=(a,b)=>{S(a,b,"createQuery",O)},
|
||||
Dc=(a,b)=>{for(var c=0;c<a;c++){var d=K.h.createQueryEXT();if(!d){for(R||=1282;c<a;)q()[b+4*c++>>2]=0;break}var f=Uf(O);d.name=f;O[f]=d;q()[b+4*c>>2]=f}},Ec=(a,b)=>{S(a,b,"createRenderbuffer",Nf)},Fc=(a,b)=>{S(a,b,"createSampler",P)},Gc=(a,b)=>{S(a,b,"createTexture",M)},Hc=(a,b)=>{S(a,b,"createVertexArray",Of)},Ic=a=>K.generateMipmap(a),Jc=(a,b,c)=>{c?q()[c>>2]=K.getBufferParameter(a,b):R||=1281},Kc=()=>{var a=K.getError()||R;R=0;return a},Zf=(a,b)=>{t()[a>>2]=b;var c=t()[a>>2];t()[a+4>>2]=(b-c)/
|
||||
4294967296};function $f(){var a=Jf(K);return a=a.concat(a.map(b=>"GL_"+b))}
|
||||
var ag=(a,b,c)=>{if(b){var d=void 0;switch(a){case 36346:d=1;break;case 36344:0!=c&&1!=c&&(R||=1280);return;case 34814:case 36345:d=0;break;case 34466:var f=K.getParameter(34467);d=f?f.length:0;break;case 33309:if(2>T.version){R||=1282;return}d=$f().length;break;case 33307:case 33308:if(2>T.version){R||=1280;return}d=33307==a?3:0}if(void 0===d)switch(f=K.getParameter(a),typeof f){case "number":d=f;break;case "boolean":d=f?1:0;break;case "string":R||=1280;return;case "object":if(null===f)switch(a){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:d=
|
||||
0;break;default:R||=1280;return}else{if(f instanceof Float32Array||f instanceof Uint32Array||f instanceof Int32Array||f instanceof Array){for(a=0;a<f.length;++a)switch(c){case 0:q()[b+4*a>>2]=f[a];break;case 2:u()[b+4*a>>2]=f[a];break;case 4:aa()[b+a]=f[a]?1:0}return}try{d=f.name|0}catch(g){R||=1280;y(`GL_INVALID_ENUM in glGet${c}v: Unknown object returned from WebGL getParameter(${a})! (error: ${g})`);return}}break;default:R||=1280;y(`GL_INVALID_ENUM in glGet${c}v: Native code calling glGet${c}v(${a}) and it returns ${f} of type ${typeof f}!`);
|
||||
return}switch(c){case 1:Zf(b,d);break;case 0:q()[b>>2]=d;break;case 2:u()[b>>2]=d;break;case 4:aa()[b]=d?1:0}}else R||=1281},Lc=(a,b)=>ag(a,b,2),Mc=(a,b,c,d)=>{a=K.getFramebufferAttachmentParameter(a,b,c);if(a instanceof WebGLRenderbuffer||a instanceof WebGLTexture)a=a.name|0;q()[d>>2]=a},Nc=(a,b)=>ag(a,b,0),Oc=(a,b,c,d)=>{a=K.getProgramInfoLog(L[a]);null===a&&(a="(unknown error)");b=0<b&&d?J(a,d,b):0;c&&(q()[c>>2]=b)},Pc=(a,b,c)=>{if(c)if(a>=Kf)R||=1281;else if(a=L[a],35716==b)a=K.getProgramInfoLog(a),
|
||||
null===a&&(a="(unknown error)"),q()[c>>2]=a.length+1;else if(35719==b){if(!a.H){var d=K.getProgramParameter(a,35718);for(b=0;b<d;++b)a.H=Math.max(a.H,K.getActiveUniform(a,b).name.length+1)}q()[c>>2]=a.H}else if(35722==b){if(!a.F)for(d=K.getProgramParameter(a,35721),b=0;b<d;++b)a.F=Math.max(a.F,K.getActiveAttrib(a,b).name.length+1);q()[c>>2]=a.F}else if(35381==b){if(!a.G)for(d=K.getProgramParameter(a,35382),b=0;b<d;++b)a.G=Math.max(a.G,K.getActiveUniformBlockName(a,b).length+1);q()[c>>2]=a.G}else q()[c>>
|
||||
2]=K.getProgramParameter(a,b);else R||=1281},Qc=(a,b,c)=>{if(c){a=O[a];b=2>T.version?K.h.getQueryObjectEXT(a,b):K.getQueryParameter(a,b);var d;"boolean"==typeof b?d=b?1:0:d=b;Zf(c,d)}else R||=1281},Rc=(a,b,c)=>{if(c){a=K.getQueryParameter(O[a],b);var d;"boolean"==typeof a?d=a?1:0:d=a;q()[c>>2]=d}else R||=1281},Sc=(a,b,c)=>{if(c){a=K.h.getQueryObjectEXT(O[a],b);var d;"boolean"==typeof a?d=a?1:0:d=a;q()[c>>2]=d}else R||=1281},Tc=(a,b,c)=>{c?q()[c>>2]=K.getQuery(a,b):R||=1281},Uc=(a,b,c)=>{c?q()[c>>
|
||||
2]=K.h.getQueryEXT(a,b):R||=1281},Vc=(a,b,c)=>{c?q()[c>>2]=K.getRenderbufferParameter(a,b):R||=1281},Wc=(a,b,c,d)=>{a=K.getShaderInfoLog(N[a]);null===a&&(a="(unknown error)");b=0<b&&d?J(a,d,b):0;c&&(q()[c>>2]=b)},Xc=(a,b,c,d)=>{a=K.getShaderPrecisionFormat(a,b);q()[c>>2]=a.rangeMin;q()[c+4>>2]=a.rangeMax;q()[d>>2]=a.precision},Yc=(a,b,c)=>{c?35716==b?(a=K.getShaderInfoLog(N[a]),null===a&&(a="(unknown error)"),a=a?a.length+1:0,q()[c>>2]=a):35720==b?(a=(a=K.getShaderSource(N[a]))?a.length+1:0,q()[c>>
|
||||
2]=a):q()[c>>2]=K.getShaderParameter(N[a],b):R||=1281},bg=a=>{for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);127>=d?b++:2047>=d?b+=2:55296<=d&&57343>=d?(b+=4,++c):b+=3}b+=1;(c=xf(b))&&J(a,c,b);return c},Zc=a=>{var b=Qf[a];if(!b){switch(a){case 7939:b=bg($f().join(" "));break;case 7936:case 7937:case 37445:case 37446:(b=K.getParameter(a))||(R||=1280);b=b?bg(b):0;break;case 7938:b=K.getParameter(7938);var c=`OpenGL ES 2.0 (${b})`;2<=T.version&&(c=`OpenGL ES 3.0 (${b})`);b=bg(c);break;case 35724:b=
|
||||
K.getParameter(35724);c=b.match(/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/);null!==c&&(3==c[1].length&&(c[1]+="0"),b=`OpenGL ES GLSL ES ${c[1]} (${b})`);b=bg(b);break;default:R||=1280}Qf[a]=b}return b},$c=(a,b)=>{if(2>T.version)return R||=1282,0;var c=Rf[a];if(c)return 0>b||b>=c.length?(R||=1281,0):c[b];switch(a){case 7939:return c=$f().map(bg),c=Rf[a]=c,0>b||b>=c.length?(R||=1281,0):c[b];default:return R||=1280,0}},cg=a=>"]"==a.slice(-1)&&a.lastIndexOf("["),ad=(a,b)=>{b=wf(b);if(a=L[a]){var c=
|
||||
a,d=c.C,f=c.W,g;if(!d){c.C=d={};c.V={};var l=K.getProgramParameter(c,35718);for(g=0;g<l;++g){var m=K.getActiveUniform(c,g);var p=m.name;m=m.size;var r=cg(p);r=0<r?p.slice(0,r):p;var F=c.N;c.N+=m;f[r]=[m,F];for(p=0;p<m;++p)d[F]=p,c.V[F++]=r}}c=a.C;d=0;f=b;g=cg(b);0<g&&(d=parseInt(b.slice(g+1))>>>0,f=b.slice(0,g));if((f=a.W[f])&&d<f[0]&&(d+=f[1],c[d]=c[d]||K.getUniformLocation(a,b)))return d}else R||=1281;return-1},bd=(a,b,c)=>{for(var d=Yf[b],f=0;f<b;f++)d[f]=q()[c+4*f>>2];K.invalidateFramebuffer(a,
|
||||
d)},cd=(a,b,c,d,f,g,l)=>{for(var m=Yf[b],p=0;p<b;p++)m[p]=q()[c+4*p>>2];K.invalidateSubFramebuffer(a,m,d,f,g,l)},dd=a=>K.isSync(Q[a]),ed=a=>(a=M[a])?K.isTexture(a):0,fd=a=>K.lineWidth(a),gd=a=>{a=L[a];K.linkProgram(a);a.C=0;a.W={}},hd=(a,b,c,d,f,g)=>{K.S.multiDrawArraysInstancedBaseInstanceWEBGL(a,q(),b>>2,q(),c>>2,q(),d>>2,t(),f>>2,g)},jd=(a,b,c,d,f,g,l,m)=>{K.S.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(a,q(),b>>2,c,q(),d>>2,q(),f>>2,q(),g>>2,t(),l>>2,m)},kd=(a,b)=>{3317==a?Sf=b:3314==
|
||||
a&&(Tf=b);K.pixelStorei(a,b)},ld=(a,b)=>{K.h.queryCounterEXT(O[a],b)},md=a=>K.readBuffer(a),dg=a=>{a-=5120;0==a?a=aa():1==a?a=n():2==a?(e.buffer!=h.buffer&&k(),a=ua):4==a?a=q():6==a?a=u():5==a||28922==a||28520==a||30779==a||30782==a?a=t():(e.buffer!=h.buffer&&k(),a=va);return a},eg=(a,b,c,d,f)=>{a=dg(a);b=d*((Tf||c)*({5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4}[b-6402]||1)*a.BYTES_PER_ELEMENT+Sf-1&-Sf);return a.subarray(f>>>31-Math.clz32(a.BYTES_PER_ELEMENT),f+b>>>31-Math.clz32(a.BYTES_PER_ELEMENT))},
|
||||
nd=(a,b,c,d,f,g,l)=>{if(2<=T.version)if(K.K)K.readPixels(a,b,c,d,f,g,l);else{var m=dg(g);l>>>=31-Math.clz32(m.BYTES_PER_ELEMENT);K.readPixels(a,b,c,d,f,g,m,l)}else(m=eg(g,f,c,d,l))?K.readPixels(a,b,c,d,f,g,m):R||=1280},od=(a,b,c,d)=>K.renderbufferStorage(a,b,c,d),pd=(a,b,c,d,f)=>K.renderbufferStorageMultisample(a,b,c,d,f),qd=(a,b,c)=>{K.samplerParameterf(P[a],b,c)},rd=(a,b,c)=>{K.samplerParameteri(P[a],b,c)},sd=(a,b,c)=>{c=q()[c>>2];K.samplerParameteri(P[a],b,c)},td=(a,b,c,d)=>K.scissor(a,b,c,d),
|
||||
ud=(a,b,c,d)=>{for(var f="",g=0;g<b;++g){var l=d?t()[d+4*g>>2]:void 0;f+=wf(t()[c+4*g>>2],l)}K.shaderSource(N[a],f)},vd=(a,b,c)=>K.stencilFunc(a,b,c),wd=(a,b,c,d)=>K.stencilFuncSeparate(a,b,c,d),xd=a=>K.stencilMask(a),yd=(a,b)=>K.stencilMaskSeparate(a,b),zd=(a,b,c)=>K.stencilOp(a,b,c),Ad=(a,b,c,d)=>K.stencilOpSeparate(a,b,c,d),Bd=(a,b,c,d,f,g,l,m,p)=>{if(2<=T.version){if(K.v){K.texImage2D(a,b,c,d,f,g,l,m,p);return}if(p){var r=dg(m);p>>>=31-Math.clz32(r.BYTES_PER_ELEMENT);K.texImage2D(a,b,c,d,f,g,
|
||||
l,m,r,p);return}}r=p?eg(m,l,d,f,p):null;K.texImage2D(a,b,c,d,f,g,l,m,r)},Cd=(a,b,c)=>K.texParameterf(a,b,c),Dd=(a,b,c)=>{c=u()[c>>2];K.texParameterf(a,b,c)},Ed=(a,b,c)=>K.texParameteri(a,b,c),Fd=(a,b,c)=>{c=q()[c>>2];K.texParameteri(a,b,c)},Gd=(a,b,c,d,f)=>K.texStorage2D(a,b,c,d,f),Hd=(a,b,c,d,f,g,l,m,p)=>{if(2<=T.version){if(K.v){K.texSubImage2D(a,b,c,d,f,g,l,m,p);return}if(p){var r=dg(m);K.texSubImage2D(a,b,c,d,f,g,l,m,r,p>>>31-Math.clz32(r.BYTES_PER_ELEMENT));return}}p=p?eg(m,l,f,g,p):null;K.texSubImage2D(a,
|
||||
b,c,d,f,g,l,m,p)},U=a=>{var b=K.Z;if(b){var c=b.C[a];"number"==typeof c&&(b.C[a]=c=K.getUniformLocation(b,b.V[a]+(0<c?`[${c}]`:"")));return c}R||=1282},Id=(a,b)=>{K.uniform1f(U(a),b)},V=[],Jd=(a,b,c)=>{if(2<=T.version)b&&K.uniform1fv(U(a),u(),c>>2,b);else{if(288>=b)for(var d=V[b],f=0;f<b;++f)d[f]=u()[c+4*f>>2];else d=u().subarray(c>>2,c+4*b>>2);K.uniform1fv(U(a),d)}},Kd=(a,b)=>{K.uniform1i(U(a),b)},fg=[],Ld=(a,b,c)=>{if(2<=T.version)b&&K.uniform1iv(U(a),q(),c>>2,b);else{if(288>=b)for(var d=fg[b],
|
||||
f=0;f<b;++f)d[f]=q()[c+4*f>>2];else d=q().subarray(c>>2,c+4*b>>2);K.uniform1iv(U(a),d)}},Md=(a,b,c)=>{K.uniform2f(U(a),b,c)},Nd=(a,b,c)=>{if(2<=T.version)b&&K.uniform2fv(U(a),u(),c>>2,2*b);else{if(144>=b){b*=2;for(var d=V[b],f=0;f<b;f+=2)d[f]=u()[c+4*f>>2],d[f+1]=u()[c+(4*f+4)>>2]}else d=u().subarray(c>>2,c+8*b>>2);K.uniform2fv(U(a),d)}},Od=(a,b,c)=>{K.uniform2i(U(a),b,c)},Pd=(a,b,c)=>{if(2<=T.version)b&&K.uniform2iv(U(a),q(),c>>2,2*b);else{if(144>=b){b*=2;for(var d=fg[b],f=0;f<b;f+=2)d[f]=q()[c+
|
||||
4*f>>2],d[f+1]=q()[c+(4*f+4)>>2]}else d=q().subarray(c>>2,c+8*b>>2);K.uniform2iv(U(a),d)}},Qd=(a,b,c,d)=>{K.uniform3f(U(a),b,c,d)},Rd=(a,b,c)=>{if(2<=T.version)b&&K.uniform3fv(U(a),u(),c>>2,3*b);else{if(96>=b){b*=3;for(var d=V[b],f=0;f<b;f+=3)d[f]=u()[c+4*f>>2],d[f+1]=u()[c+(4*f+4)>>2],d[f+2]=u()[c+(4*f+8)>>2]}else d=u().subarray(c>>2,c+12*b>>2);K.uniform3fv(U(a),d)}},Sd=(a,b,c,d)=>{K.uniform3i(U(a),b,c,d)},Td=(a,b,c)=>{if(2<=T.version)b&&K.uniform3iv(U(a),q(),c>>2,3*b);else{if(96>=b){b*=3;for(var d=
|
||||
fg[b],f=0;f<b;f+=3)d[f]=q()[c+4*f>>2],d[f+1]=q()[c+(4*f+4)>>2],d[f+2]=q()[c+(4*f+8)>>2]}else d=q().subarray(c>>2,c+12*b>>2);K.uniform3iv(U(a),d)}},Ud=(a,b,c,d,f)=>{K.uniform4f(U(a),b,c,d,f)},Vd=(a,b,c)=>{if(2<=T.version)b&&K.uniform4fv(U(a),u(),c>>2,4*b);else{if(72>=b){var d=V[4*b],f=u();c>>=2;b*=4;for(var g=0;g<b;g+=4){var l=c+g;d[g]=f[l];d[g+1]=f[l+1];d[g+2]=f[l+2];d[g+3]=f[l+3]}}else d=u().subarray(c>>2,c+16*b>>2);K.uniform4fv(U(a),d)}},Wd=(a,b,c,d,f)=>{K.uniform4i(U(a),b,c,d,f)},Xd=(a,b,c)=>{if(2<=
|
||||
T.version)b&&K.uniform4iv(U(a),q(),c>>2,4*b);else{if(72>=b){b*=4;for(var d=fg[b],f=0;f<b;f+=4)d[f]=q()[c+4*f>>2],d[f+1]=q()[c+(4*f+4)>>2],d[f+2]=q()[c+(4*f+8)>>2],d[f+3]=q()[c+(4*f+12)>>2]}else d=q().subarray(c>>2,c+16*b>>2);K.uniform4iv(U(a),d)}},Yd=(a,b,c,d)=>{if(2<=T.version)b&&K.uniformMatrix2fv(U(a),!!c,u(),d>>2,4*b);else{if(72>=b){b*=4;for(var f=V[b],g=0;g<b;g+=4)f[g]=u()[d+4*g>>2],f[g+1]=u()[d+(4*g+4)>>2],f[g+2]=u()[d+(4*g+8)>>2],f[g+3]=u()[d+(4*g+12)>>2]}else f=u().subarray(d>>2,d+16*b>>2);
|
||||
K.uniformMatrix2fv(U(a),!!c,f)}},Zd=(a,b,c,d)=>{if(2<=T.version)b&&K.uniformMatrix3fv(U(a),!!c,u(),d>>2,9*b);else{if(32>=b){b*=9;for(var f=V[b],g=0;g<b;g+=9)f[g]=u()[d+4*g>>2],f[g+1]=u()[d+(4*g+4)>>2],f[g+2]=u()[d+(4*g+8)>>2],f[g+3]=u()[d+(4*g+12)>>2],f[g+4]=u()[d+(4*g+16)>>2],f[g+5]=u()[d+(4*g+20)>>2],f[g+6]=u()[d+(4*g+24)>>2],f[g+7]=u()[d+(4*g+28)>>2],f[g+8]=u()[d+(4*g+32)>>2]}else f=u().subarray(d>>2,d+36*b>>2);K.uniformMatrix3fv(U(a),!!c,f)}},$d=(a,b,c,d)=>{if(2<=T.version)b&&K.uniformMatrix4fv(U(a),
|
||||
!!c,u(),d>>2,16*b);else{if(18>=b){var f=V[16*b],g=u();d>>=2;b*=16;for(var l=0;l<b;l+=16){var m=d+l;f[l]=g[m];f[l+1]=g[m+1];f[l+2]=g[m+2];f[l+3]=g[m+3];f[l+4]=g[m+4];f[l+5]=g[m+5];f[l+6]=g[m+6];f[l+7]=g[m+7];f[l+8]=g[m+8];f[l+9]=g[m+9];f[l+10]=g[m+10];f[l+11]=g[m+11];f[l+12]=g[m+12];f[l+13]=g[m+13];f[l+14]=g[m+14];f[l+15]=g[m+15]}}else f=u().subarray(d>>2,d+64*b>>2);K.uniformMatrix4fv(U(a),!!c,f)}},ae=a=>{a=L[a];K.useProgram(a);K.Z=a},be=(a,b)=>K.vertexAttrib1f(a,b),ce=(a,b)=>{K.vertexAttrib2f(a,u()[b>>
|
||||
2],u()[b+4>>2])},de=(a,b)=>{K.vertexAttrib3f(a,u()[b>>2],u()[b+4>>2],u()[b+8>>2])},ee=(a,b)=>{K.vertexAttrib4f(a,u()[b>>2],u()[b+4>>2],u()[b+8>>2],u()[b+12>>2])},fe=(a,b)=>{K.vertexAttribDivisor(a,b)},ge=(a,b,c,d,f)=>{K.vertexAttribIPointer(a,b,c,d,f)},he=(a,b,c,d,f,g)=>{K.vertexAttribPointer(a,b,c,!!d,f,g)},ie=(a,b,c,d)=>K.viewport(a,b,c,d),je=(a,b,c,d)=>{K.waitSync(Q[a],b,(c>>>0)+4294967296*d)},ke=a=>{var b=n().length;a>>>=0;if(a<=b||2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);
|
||||
d=Math.min(d,a+100663296);a:{d=(Math.min(2147483648,65536*Math.ceil(Math.max(a,d)/65536))-e.buffer.byteLength+65535)/65536|0;try{e.grow(d);k();var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1};
|
||||
function le(a,b){a=Pf[a];b=wf(b);b.startsWith("GL_")&&(b=b.substr(3));"ANGLE_instanced_arrays"==b&&Ef(K);"OES_vertex_array_object"==b&&Ff(K);"WEBGL_draw_buffers"==b&&Gf(K);"WEBGL_draw_instanced_base_vertex_base_instance"==b&&Hf(K);"WEBGL_multi_draw_instanced_base_vertex_base_instance"==b&&If(K);"WEBGL_multi_draw"==b&&(K.fa=K.getExtension("WEBGL_multi_draw"));"EXT_polygon_offset_clamp"==b&&(K.aa=K.getExtension("EXT_polygon_offset_clamp"));"EXT_clip_control"==b&&(K.$=K.getExtension("EXT_clip_control"));
|
||||
"WEBGL_polygon_mode"==b&&(K.ra=K.getExtension("WEBGL_polygon_mode"));return!!a.D.getExtension(b)}
|
||||
var me=()=>T?T.handle:0,ne=a=>{T=Pf[a];v.ta=K=T?.D;return!a||K?0:-5},gg={},ig=()=>{if(!hg){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:"./this.program"},b;for(b in gg)void 0===gg[b]?delete a[b]:a[b]=gg[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);hg=c}return hg},hg;
|
||||
function oe(a,b){if(w)return H(10,1,a,b);var c=0;ig().forEach((d,f)=>{var g=b+c;f=t()[a+4*f>>2]=g;for(g=0;g<d.length;++g)aa()[f++]=d.charCodeAt(g);aa()[f]=0;c+=d.length+1});return 0}function pe(a,b){if(w)return H(11,1,a,b);var c=ig();t()[a>>2]=c.length;var d=0;c.forEach(f=>d+=f.length+1);t()[b>>2]=d;return 0}function re(a){return w?H(12,1,a):52}function se(a,b,c,d,f,g){return w?H(13,1,a,b,c,d,f,g):52}function te(a,b,c,d){return w?H(14,1,a,b,c,d):52}
|
||||
function ue(a,b,c,d,f){return w?H(15,1,a,b,c,d,f):70}var jg=[null,[],[]];function ve(a,b,c,d){if(w)return H(16,1,a,b,c,d);for(var f=0,g=0;g<c;g++){var l=t()[b>>2],m=t()[b+4>>2];b+=8;for(var p=0;p<m;p++){var r=n()[l+p],F=jg[a];0===r||10===r?((1===a?qa:y)(vf(F)),F.length=0):F.push(r)}f+=m}t()[d>>2]=f;return 0}function kg(){}function lg(){}function W(){}function He(){}function Ie(){}function Je(){}function Ke(){}function Le(){}function Me(){}function Ne(){}function Oe(){}function Pe(){}
|
||||
function Qe(){}function Re(){}function Se(){}function Te(){}var mg,ng=[];w||gf();for(var X=0;32>X;++X)Yf.push(Array(X));var og=new Float32Array(288);for(X=0;288>=X;++X)V[X]=og.subarray(0,X);var pg=new Int32Array(288);for(X=0;288>=X;++X)fg[X]=pg.subarray(0,X);
|
||||
(function(){const a=new Map,b=new Map;Te=function(c,d,f){W({m:"setAssociatedObject",M:d,object:f},[f],c)};Pe=function(c){return b.get(c)};Ie=function(c){kg(c,function(d){var f=d.m;if(f)switch(f){case "renderPictures":qg(d.o,d.ha,d.ga,d.s,lg());break;case "onRenderComplete":sg(d.o,d.s,{imageBitmaps:d.da,rasterStartMilliseconds:d.ja,rasterEndMilliseconds:d.ia});break;case "setAssociatedObject":b.set(d.M,d.object);break;case "disposeAssociatedObject":d=d.M;f=b.get(d);f.close&&f.close();b.delete(d);break;
|
||||
case "disposeSurface":tg(d.o);break;case "rasterizeImage":ug(d.o,d.image,d.format,d.s);break;case "onRasterizeComplete":vg(d.o,d.data,d.s);break;default:console.warn(`unrecognized skwasm message: ${f}`)}})};Ne=function(c,d,f,g,l){W({m:"renderPictures",o:d,ha:f,ga:g,s:l},[],c)};Ke=function(c,d){c=new OffscreenCanvas(c,d);d=Wf(c);a.set(d,c);return d};Re=function(c,d,f){c=a.get(c);c.width=d;c.height=f};He=function(c,d,f,g){g||=[];c=a.get(c);g.push(createImageBitmap(c,0,0,d,f));return g};Se=async function(c,
|
||||
d,f,g){d=d?await Promise.all(d):[];W({m:"onRenderComplete",o:c,s:g,da:d,ja:f,ia:lg()},[...d])};Je=function(c,d,f){const g=T.D,l=g.createTexture();g.bindTexture(g.TEXTURE_2D,l);g.pixelStorei(g.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0);g.texImage2D(g.TEXTURE_2D,0,g.RGBA,d,f,0,g.RGBA,g.UNSIGNED_BYTE,c);g.pixelStorei(g.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);g.bindTexture(g.TEXTURE_2D,null);c=Uf(M);M[c]=l;return c};Oe=function(c,d){W({m:"disposeAssociatedObject",M:d},[],c)};Le=function(c,d){W({m:"disposeSurface",
|
||||
o:d},[],c)};Me=function(c,d,f,g,l){W({m:"rasterizeImage",o:d,image:f,format:g,s:l},[],c)};Qe=function(c,d,f){W({m:"onRasterizeComplete",o:c,data:d,s:f})}})();
|
||||
(function(){let a=0;kg=function(b,c){function d({data:f}){const g=f.m;g&&("syncTimeOrigin"==g?a=performance.timeOrigin-f.timeOrigin:c(f))}b?(B[b].addEventListener("message",d),B[b].postMessage({m:"syncTimeOrigin",timeOrigin:performance.timeOrigin})):addEventListener("message",d)};lg=function(){return performance.now()+a};W=function(b,c,d){d?B[d].postMessage(b,c):postMessage(b,c)}})();
|
||||
var Bf=[Ge,ef,tf,Xa,Ya,Za,$a,jb,kb,lb,oe,pe,re,se,te,ue,ve],Ua,Y=function(){function a(c,d){Y=c.exports;v.wasmExports=Y;ff.push(Y._emscripten_tls_init);I=Y.__indirect_function_table;Ja.unshift(Y.__wasm_call_ctors);ra=d;Na();return Y}var b=za();z++;if(v.instantiateWasm)try{return v.instantiateWasm(b,a)}catch(c){y(`Module.instantiateWasm callback failed with error: ${c}`),ja(c)}Qa??=Pa("skwasm.wasm")?"skwasm.wasm":x+"skwasm.wasm";Ta(b,function(c){a(c.instance,c.module)}).catch(ja);return{}}();
|
||||
v._canvas_saveLayer=(a,b,c,d,f)=>(v._canvas_saveLayer=Y.canvas_saveLayer)(a,b,c,d,f);v._canvas_save=a=>(v._canvas_save=Y.canvas_save)(a);v._canvas_restore=a=>(v._canvas_restore=Y.canvas_restore)(a);v._canvas_restoreToCount=(a,b)=>(v._canvas_restoreToCount=Y.canvas_restoreToCount)(a,b);v._canvas_getSaveCount=a=>(v._canvas_getSaveCount=Y.canvas_getSaveCount)(a);v._canvas_translate=(a,b,c)=>(v._canvas_translate=Y.canvas_translate)(a,b,c);
|
||||
v._canvas_scale=(a,b,c)=>(v._canvas_scale=Y.canvas_scale)(a,b,c);v._canvas_rotate=(a,b)=>(v._canvas_rotate=Y.canvas_rotate)(a,b);v._canvas_skew=(a,b,c)=>(v._canvas_skew=Y.canvas_skew)(a,b,c);v._canvas_transform=(a,b)=>(v._canvas_transform=Y.canvas_transform)(a,b);v._canvas_clipRect=(a,b,c,d)=>(v._canvas_clipRect=Y.canvas_clipRect)(a,b,c,d);v._canvas_clipRRect=(a,b,c)=>(v._canvas_clipRRect=Y.canvas_clipRRect)(a,b,c);v._canvas_clipPath=(a,b,c)=>(v._canvas_clipPath=Y.canvas_clipPath)(a,b,c);
|
||||
v._canvas_drawColor=(a,b,c)=>(v._canvas_drawColor=Y.canvas_drawColor)(a,b,c);v._canvas_drawLine=(a,b,c,d,f,g)=>(v._canvas_drawLine=Y.canvas_drawLine)(a,b,c,d,f,g);v._canvas_drawPaint=(a,b)=>(v._canvas_drawPaint=Y.canvas_drawPaint)(a,b);v._canvas_drawRect=(a,b,c)=>(v._canvas_drawRect=Y.canvas_drawRect)(a,b,c);v._canvas_drawRRect=(a,b,c)=>(v._canvas_drawRRect=Y.canvas_drawRRect)(a,b,c);v._canvas_drawDRRect=(a,b,c,d)=>(v._canvas_drawDRRect=Y.canvas_drawDRRect)(a,b,c,d);
|
||||
v._canvas_drawOval=(a,b,c)=>(v._canvas_drawOval=Y.canvas_drawOval)(a,b,c);v._canvas_drawCircle=(a,b,c,d,f)=>(v._canvas_drawCircle=Y.canvas_drawCircle)(a,b,c,d,f);v._canvas_drawArc=(a,b,c,d,f,g)=>(v._canvas_drawArc=Y.canvas_drawArc)(a,b,c,d,f,g);v._canvas_drawPath=(a,b,c)=>(v._canvas_drawPath=Y.canvas_drawPath)(a,b,c);v._canvas_drawShadow=(a,b,c,d,f,g)=>(v._canvas_drawShadow=Y.canvas_drawShadow)(a,b,c,d,f,g);
|
||||
v._canvas_drawParagraph=(a,b,c,d)=>(v._canvas_drawParagraph=Y.canvas_drawParagraph)(a,b,c,d);v._canvas_drawPicture=(a,b)=>(v._canvas_drawPicture=Y.canvas_drawPicture)(a,b);v._canvas_drawImage=(a,b,c,d,f,g)=>(v._canvas_drawImage=Y.canvas_drawImage)(a,b,c,d,f,g);v._canvas_drawImageRect=(a,b,c,d,f,g)=>(v._canvas_drawImageRect=Y.canvas_drawImageRect)(a,b,c,d,f,g);v._canvas_drawImageNine=(a,b,c,d,f,g)=>(v._canvas_drawImageNine=Y.canvas_drawImageNine)(a,b,c,d,f,g);
|
||||
v._canvas_drawVertices=(a,b,c,d)=>(v._canvas_drawVertices=Y.canvas_drawVertices)(a,b,c,d);v._canvas_drawPoints=(a,b,c,d,f)=>(v._canvas_drawPoints=Y.canvas_drawPoints)(a,b,c,d,f);v._canvas_drawAtlas=(a,b,c,d,f,g,l,m,p)=>(v._canvas_drawAtlas=Y.canvas_drawAtlas)(a,b,c,d,f,g,l,m,p);v._canvas_getTransform=(a,b)=>(v._canvas_getTransform=Y.canvas_getTransform)(a,b);v._canvas_getLocalClipBounds=(a,b)=>(v._canvas_getLocalClipBounds=Y.canvas_getLocalClipBounds)(a,b);
|
||||
v._canvas_getDeviceClipBounds=(a,b)=>(v._canvas_getDeviceClipBounds=Y.canvas_getDeviceClipBounds)(a,b);v._contourMeasureIter_create=(a,b,c)=>(v._contourMeasureIter_create=Y.contourMeasureIter_create)(a,b,c);v._contourMeasureIter_next=a=>(v._contourMeasureIter_next=Y.contourMeasureIter_next)(a);v._contourMeasureIter_dispose=a=>(v._contourMeasureIter_dispose=Y.contourMeasureIter_dispose)(a);v._contourMeasure_dispose=a=>(v._contourMeasure_dispose=Y.contourMeasure_dispose)(a);
|
||||
v._contourMeasure_length=a=>(v._contourMeasure_length=Y.contourMeasure_length)(a);v._contourMeasure_isClosed=a=>(v._contourMeasure_isClosed=Y.contourMeasure_isClosed)(a);v._contourMeasure_getPosTan=(a,b,c,d)=>(v._contourMeasure_getPosTan=Y.contourMeasure_getPosTan)(a,b,c,d);v._contourMeasure_getSegment=(a,b,c,d)=>(v._contourMeasure_getSegment=Y.contourMeasure_getSegment)(a,b,c,d);v._skData_create=a=>(v._skData_create=Y.skData_create)(a);v._skData_getPointer=a=>(v._skData_getPointer=Y.skData_getPointer)(a);
|
||||
v._skData_getConstPointer=a=>(v._skData_getConstPointer=Y.skData_getConstPointer)(a);v._skData_getSize=a=>(v._skData_getSize=Y.skData_getSize)(a);v._skData_dispose=a=>(v._skData_dispose=Y.skData_dispose)(a);v._imageFilter_createBlur=(a,b,c)=>(v._imageFilter_createBlur=Y.imageFilter_createBlur)(a,b,c);v._imageFilter_createDilate=(a,b)=>(v._imageFilter_createDilate=Y.imageFilter_createDilate)(a,b);v._imageFilter_createErode=(a,b)=>(v._imageFilter_createErode=Y.imageFilter_createErode)(a,b);
|
||||
v._imageFilter_createMatrix=(a,b)=>(v._imageFilter_createMatrix=Y.imageFilter_createMatrix)(a,b);v._imageFilter_createFromColorFilter=a=>(v._imageFilter_createFromColorFilter=Y.imageFilter_createFromColorFilter)(a);v._imageFilter_compose=(a,b)=>(v._imageFilter_compose=Y.imageFilter_compose)(a,b);v._imageFilter_dispose=a=>(v._imageFilter_dispose=Y.imageFilter_dispose)(a);v._imageFilter_getFilterBounds=(a,b)=>(v._imageFilter_getFilterBounds=Y.imageFilter_getFilterBounds)(a,b);
|
||||
v._colorFilter_createMode=(a,b)=>(v._colorFilter_createMode=Y.colorFilter_createMode)(a,b);v._colorFilter_createMatrix=a=>(v._colorFilter_createMatrix=Y.colorFilter_createMatrix)(a);v._colorFilter_createSRGBToLinearGamma=()=>(v._colorFilter_createSRGBToLinearGamma=Y.colorFilter_createSRGBToLinearGamma)();v._colorFilter_createLinearToSRGBGamma=()=>(v._colorFilter_createLinearToSRGBGamma=Y.colorFilter_createLinearToSRGBGamma)();
|
||||
v._colorFilter_compose=(a,b)=>(v._colorFilter_compose=Y.colorFilter_compose)(a,b);v._colorFilter_dispose=a=>(v._colorFilter_dispose=Y.colorFilter_dispose)(a);v._maskFilter_createBlur=(a,b)=>(v._maskFilter_createBlur=Y.maskFilter_createBlur)(a,b);v._maskFilter_dispose=a=>(v._maskFilter_dispose=Y.maskFilter_dispose)(a);v._fontCollection_create=()=>(v._fontCollection_create=Y.fontCollection_create)();v._fontCollection_dispose=a=>(v._fontCollection_dispose=Y.fontCollection_dispose)(a);
|
||||
v._typeface_create=a=>(v._typeface_create=Y.typeface_create)(a);v._typeface_dispose=a=>(v._typeface_dispose=Y.typeface_dispose)(a);v._typefaces_filterCoveredCodePoints=(a,b,c,d)=>(v._typefaces_filterCoveredCodePoints=Y.typefaces_filterCoveredCodePoints)(a,b,c,d);v._fontCollection_registerTypeface=(a,b,c)=>(v._fontCollection_registerTypeface=Y.fontCollection_registerTypeface)(a,b,c);v._fontCollection_clearCaches=a=>(v._fontCollection_clearCaches=Y.fontCollection_clearCaches)(a);
|
||||
v._image_createFromPicture=(a,b,c)=>(v._image_createFromPicture=Y.image_createFromPicture)(a,b,c);v._image_createFromPixels=(a,b,c,d,f)=>(v._image_createFromPixels=Y.image_createFromPixels)(a,b,c,d,f);v._image_createFromTextureSource=(a,b,c,d)=>(v._image_createFromTextureSource=Y.image_createFromTextureSource)(a,b,c,d);v._image_ref=a=>(v._image_ref=Y.image_ref)(a);v._image_dispose=a=>(v._image_dispose=Y.image_dispose)(a);v._image_getWidth=a=>(v._image_getWidth=Y.image_getWidth)(a);
|
||||
v._image_getHeight=a=>(v._image_getHeight=Y.image_getHeight)(a);v._paint_create=(a,b,c,d,f,g,l,m)=>(v._paint_create=Y.paint_create)(a,b,c,d,f,g,l,m);v._paint_dispose=a=>(v._paint_dispose=Y.paint_dispose)(a);v._paint_setShader=(a,b)=>(v._paint_setShader=Y.paint_setShader)(a,b);v._paint_setImageFilter=(a,b)=>(v._paint_setImageFilter=Y.paint_setImageFilter)(a,b);v._paint_setColorFilter=(a,b)=>(v._paint_setColorFilter=Y.paint_setColorFilter)(a,b);
|
||||
v._paint_setMaskFilter=(a,b)=>(v._paint_setMaskFilter=Y.paint_setMaskFilter)(a,b);v._path_create=()=>(v._path_create=Y.path_create)();v._path_dispose=a=>(v._path_dispose=Y.path_dispose)(a);v._path_copy=a=>(v._path_copy=Y.path_copy)(a);v._path_setFillType=(a,b)=>(v._path_setFillType=Y.path_setFillType)(a,b);v._path_getFillType=a=>(v._path_getFillType=Y.path_getFillType)(a);v._path_moveTo=(a,b,c)=>(v._path_moveTo=Y.path_moveTo)(a,b,c);
|
||||
v._path_relativeMoveTo=(a,b,c)=>(v._path_relativeMoveTo=Y.path_relativeMoveTo)(a,b,c);v._path_lineTo=(a,b,c)=>(v._path_lineTo=Y.path_lineTo)(a,b,c);v._path_relativeLineTo=(a,b,c)=>(v._path_relativeLineTo=Y.path_relativeLineTo)(a,b,c);v._path_quadraticBezierTo=(a,b,c,d,f)=>(v._path_quadraticBezierTo=Y.path_quadraticBezierTo)(a,b,c,d,f);v._path_relativeQuadraticBezierTo=(a,b,c,d,f)=>(v._path_relativeQuadraticBezierTo=Y.path_relativeQuadraticBezierTo)(a,b,c,d,f);
|
||||
v._path_cubicTo=(a,b,c,d,f,g,l)=>(v._path_cubicTo=Y.path_cubicTo)(a,b,c,d,f,g,l);v._path_relativeCubicTo=(a,b,c,d,f,g,l)=>(v._path_relativeCubicTo=Y.path_relativeCubicTo)(a,b,c,d,f,g,l);v._path_conicTo=(a,b,c,d,f,g)=>(v._path_conicTo=Y.path_conicTo)(a,b,c,d,f,g);v._path_relativeConicTo=(a,b,c,d,f,g)=>(v._path_relativeConicTo=Y.path_relativeConicTo)(a,b,c,d,f,g);v._path_arcToOval=(a,b,c,d,f)=>(v._path_arcToOval=Y.path_arcToOval)(a,b,c,d,f);
|
||||
v._path_arcToRotated=(a,b,c,d,f,g,l,m)=>(v._path_arcToRotated=Y.path_arcToRotated)(a,b,c,d,f,g,l,m);v._path_relativeArcToRotated=(a,b,c,d,f,g,l,m)=>(v._path_relativeArcToRotated=Y.path_relativeArcToRotated)(a,b,c,d,f,g,l,m);v._path_addRect=(a,b)=>(v._path_addRect=Y.path_addRect)(a,b);v._path_addOval=(a,b)=>(v._path_addOval=Y.path_addOval)(a,b);v._path_addArc=(a,b,c,d)=>(v._path_addArc=Y.path_addArc)(a,b,c,d);v._path_addPolygon=(a,b,c,d)=>(v._path_addPolygon=Y.path_addPolygon)(a,b,c,d);
|
||||
v._path_addRRect=(a,b)=>(v._path_addRRect=Y.path_addRRect)(a,b);v._path_addPath=(a,b,c,d)=>(v._path_addPath=Y.path_addPath)(a,b,c,d);v._path_close=a=>(v._path_close=Y.path_close)(a);v._path_reset=a=>(v._path_reset=Y.path_reset)(a);v._path_contains=(a,b,c)=>(v._path_contains=Y.path_contains)(a,b,c);v._path_transform=(a,b)=>(v._path_transform=Y.path_transform)(a,b);v._path_getBounds=(a,b)=>(v._path_getBounds=Y.path_getBounds)(a,b);v._path_combine=(a,b,c)=>(v._path_combine=Y.path_combine)(a,b,c);
|
||||
v._path_getSvgString=a=>(v._path_getSvgString=Y.path_getSvgString)(a);v._pictureRecorder_create=()=>(v._pictureRecorder_create=Y.pictureRecorder_create)();v._pictureRecorder_dispose=a=>(v._pictureRecorder_dispose=Y.pictureRecorder_dispose)(a);v._pictureRecorder_beginRecording=(a,b)=>(v._pictureRecorder_beginRecording=Y.pictureRecorder_beginRecording)(a,b);v._pictureRecorder_endRecording=a=>(v._pictureRecorder_endRecording=Y.pictureRecorder_endRecording)(a);
|
||||
v._picture_getCullRect=(a,b)=>(v._picture_getCullRect=Y.picture_getCullRect)(a,b);v._picture_dispose=a=>(v._picture_dispose=Y.picture_dispose)(a);v._picture_approximateBytesUsed=a=>(v._picture_approximateBytesUsed=Y.picture_approximateBytesUsed)(a);v._shader_createLinearGradient=(a,b,c,d,f,g)=>(v._shader_createLinearGradient=Y.shader_createLinearGradient)(a,b,c,d,f,g);v._shader_createRadialGradient=(a,b,c,d,f,g,l,m)=>(v._shader_createRadialGradient=Y.shader_createRadialGradient)(a,b,c,d,f,g,l,m);
|
||||
v._shader_createConicalGradient=(a,b,c,d,f,g,l,m)=>(v._shader_createConicalGradient=Y.shader_createConicalGradient)(a,b,c,d,f,g,l,m);v._shader_createSweepGradient=(a,b,c,d,f,g,l,m,p)=>(v._shader_createSweepGradient=Y.shader_createSweepGradient)(a,b,c,d,f,g,l,m,p);v._shader_dispose=a=>(v._shader_dispose=Y.shader_dispose)(a);v._runtimeEffect_create=a=>(v._runtimeEffect_create=Y.runtimeEffect_create)(a);v._runtimeEffect_dispose=a=>(v._runtimeEffect_dispose=Y.runtimeEffect_dispose)(a);
|
||||
v._runtimeEffect_getUniformSize=a=>(v._runtimeEffect_getUniformSize=Y.runtimeEffect_getUniformSize)(a);v._shader_createRuntimeEffectShader=(a,b,c,d)=>(v._shader_createRuntimeEffectShader=Y.shader_createRuntimeEffectShader)(a,b,c,d);v._shader_createFromImage=(a,b,c,d,f)=>(v._shader_createFromImage=Y.shader_createFromImage)(a,b,c,d,f);v._skString_allocate=a=>(v._skString_allocate=Y.skString_allocate)(a);v._skString_getData=a=>(v._skString_getData=Y.skString_getData)(a);
|
||||
v._skString_getLength=a=>(v._skString_getLength=Y.skString_getLength)(a);v._skString_free=a=>(v._skString_free=Y.skString_free)(a);v._skString16_allocate=a=>(v._skString16_allocate=Y.skString16_allocate)(a);v._skString16_getData=a=>(v._skString16_getData=Y.skString16_getData)(a);v._skString16_free=a=>(v._skString16_free=Y.skString16_free)(a);v._surface_create=()=>(v._surface_create=Y.surface_create)();v._surface_getThreadId=a=>(v._surface_getThreadId=Y.surface_getThreadId)(a);
|
||||
v._surface_setCallbackHandler=(a,b)=>(v._surface_setCallbackHandler=Y.surface_setCallbackHandler)(a,b);v._surface_destroy=a=>(v._surface_destroy=Y.surface_destroy)(a);var tg=v._surface_dispose=a=>(tg=v._surface_dispose=Y.surface_dispose)(a);v._surface_renderPictures=(a,b,c)=>(v._surface_renderPictures=Y.surface_renderPictures)(a,b,c);var qg=v._surface_renderPicturesOnWorker=(a,b,c,d,f)=>(qg=v._surface_renderPicturesOnWorker=Y.surface_renderPicturesOnWorker)(a,b,c,d,f);
|
||||
v._surface_rasterizeImage=(a,b,c)=>(v._surface_rasterizeImage=Y.surface_rasterizeImage)(a,b,c);var ug=v._surface_rasterizeImageOnWorker=(a,b,c,d)=>(ug=v._surface_rasterizeImageOnWorker=Y.surface_rasterizeImageOnWorker)(a,b,c,d),sg=v._surface_onRenderComplete=(a,b,c)=>(sg=v._surface_onRenderComplete=Y.surface_onRenderComplete)(a,b,c),vg=v._surface_onRasterizeComplete=(a,b,c)=>(vg=v._surface_onRasterizeComplete=Y.surface_onRasterizeComplete)(a,b,c);
|
||||
v._lineMetrics_create=(a,b,c,d,f,g,l,m,p)=>(v._lineMetrics_create=Y.lineMetrics_create)(a,b,c,d,f,g,l,m,p);v._lineMetrics_dispose=a=>(v._lineMetrics_dispose=Y.lineMetrics_dispose)(a);v._lineMetrics_getHardBreak=a=>(v._lineMetrics_getHardBreak=Y.lineMetrics_getHardBreak)(a);v._lineMetrics_getAscent=a=>(v._lineMetrics_getAscent=Y.lineMetrics_getAscent)(a);v._lineMetrics_getDescent=a=>(v._lineMetrics_getDescent=Y.lineMetrics_getDescent)(a);
|
||||
v._lineMetrics_getUnscaledAscent=a=>(v._lineMetrics_getUnscaledAscent=Y.lineMetrics_getUnscaledAscent)(a);v._lineMetrics_getHeight=a=>(v._lineMetrics_getHeight=Y.lineMetrics_getHeight)(a);v._lineMetrics_getWidth=a=>(v._lineMetrics_getWidth=Y.lineMetrics_getWidth)(a);v._lineMetrics_getLeft=a=>(v._lineMetrics_getLeft=Y.lineMetrics_getLeft)(a);v._lineMetrics_getBaseline=a=>(v._lineMetrics_getBaseline=Y.lineMetrics_getBaseline)(a);v._lineMetrics_getLineNumber=a=>(v._lineMetrics_getLineNumber=Y.lineMetrics_getLineNumber)(a);
|
||||
v._lineMetrics_getStartIndex=a=>(v._lineMetrics_getStartIndex=Y.lineMetrics_getStartIndex)(a);v._lineMetrics_getEndIndex=a=>(v._lineMetrics_getEndIndex=Y.lineMetrics_getEndIndex)(a);v._paragraph_dispose=a=>(v._paragraph_dispose=Y.paragraph_dispose)(a);v._paragraph_getWidth=a=>(v._paragraph_getWidth=Y.paragraph_getWidth)(a);v._paragraph_getHeight=a=>(v._paragraph_getHeight=Y.paragraph_getHeight)(a);v._paragraph_getLongestLine=a=>(v._paragraph_getLongestLine=Y.paragraph_getLongestLine)(a);
|
||||
v._paragraph_getMinIntrinsicWidth=a=>(v._paragraph_getMinIntrinsicWidth=Y.paragraph_getMinIntrinsicWidth)(a);v._paragraph_getMaxIntrinsicWidth=a=>(v._paragraph_getMaxIntrinsicWidth=Y.paragraph_getMaxIntrinsicWidth)(a);v._paragraph_getAlphabeticBaseline=a=>(v._paragraph_getAlphabeticBaseline=Y.paragraph_getAlphabeticBaseline)(a);v._paragraph_getIdeographicBaseline=a=>(v._paragraph_getIdeographicBaseline=Y.paragraph_getIdeographicBaseline)(a);
|
||||
v._paragraph_getDidExceedMaxLines=a=>(v._paragraph_getDidExceedMaxLines=Y.paragraph_getDidExceedMaxLines)(a);v._paragraph_layout=(a,b)=>(v._paragraph_layout=Y.paragraph_layout)(a,b);v._paragraph_getPositionForOffset=(a,b,c,d)=>(v._paragraph_getPositionForOffset=Y.paragraph_getPositionForOffset)(a,b,c,d);v._paragraph_getClosestGlyphInfoAtCoordinate=(a,b,c,d,f,g)=>(v._paragraph_getClosestGlyphInfoAtCoordinate=Y.paragraph_getClosestGlyphInfoAtCoordinate)(a,b,c,d,f,g);
|
||||
v._paragraph_getGlyphInfoAt=(a,b,c,d,f)=>(v._paragraph_getGlyphInfoAt=Y.paragraph_getGlyphInfoAt)(a,b,c,d,f);v._paragraph_getWordBoundary=(a,b,c)=>(v._paragraph_getWordBoundary=Y.paragraph_getWordBoundary)(a,b,c);v._paragraph_getLineCount=a=>(v._paragraph_getLineCount=Y.paragraph_getLineCount)(a);v._paragraph_getLineNumberAt=(a,b)=>(v._paragraph_getLineNumberAt=Y.paragraph_getLineNumberAt)(a,b);
|
||||
v._paragraph_getLineMetricsAtIndex=(a,b)=>(v._paragraph_getLineMetricsAtIndex=Y.paragraph_getLineMetricsAtIndex)(a,b);v._textBoxList_dispose=a=>(v._textBoxList_dispose=Y.textBoxList_dispose)(a);v._textBoxList_getLength=a=>(v._textBoxList_getLength=Y.textBoxList_getLength)(a);v._textBoxList_getBoxAtIndex=(a,b,c)=>(v._textBoxList_getBoxAtIndex=Y.textBoxList_getBoxAtIndex)(a,b,c);v._paragraph_getBoxesForRange=(a,b,c,d,f)=>(v._paragraph_getBoxesForRange=Y.paragraph_getBoxesForRange)(a,b,c,d,f);
|
||||
v._paragraph_getBoxesForPlaceholders=a=>(v._paragraph_getBoxesForPlaceholders=Y.paragraph_getBoxesForPlaceholders)(a);v._paragraph_getUnresolvedCodePoints=(a,b,c)=>(v._paragraph_getUnresolvedCodePoints=Y.paragraph_getUnresolvedCodePoints)(a,b,c);v._paragraphBuilder_create=(a,b)=>(v._paragraphBuilder_create=Y.paragraphBuilder_create)(a,b);v._paragraphBuilder_dispose=a=>(v._paragraphBuilder_dispose=Y.paragraphBuilder_dispose)(a);
|
||||
v._paragraphBuilder_addPlaceholder=(a,b,c,d,f,g)=>(v._paragraphBuilder_addPlaceholder=Y.paragraphBuilder_addPlaceholder)(a,b,c,d,f,g);v._paragraphBuilder_addText=(a,b)=>(v._paragraphBuilder_addText=Y.paragraphBuilder_addText)(a,b);v._paragraphBuilder_getUtf8Text=(a,b)=>(v._paragraphBuilder_getUtf8Text=Y.paragraphBuilder_getUtf8Text)(a,b);v._paragraphBuilder_pushStyle=(a,b)=>(v._paragraphBuilder_pushStyle=Y.paragraphBuilder_pushStyle)(a,b);v._paragraphBuilder_pop=a=>(v._paragraphBuilder_pop=Y.paragraphBuilder_pop)(a);
|
||||
v._paragraphBuilder_build=a=>(v._paragraphBuilder_build=Y.paragraphBuilder_build)(a);v._unicodePositionBuffer_create=a=>(v._unicodePositionBuffer_create=Y.unicodePositionBuffer_create)(a);v._unicodePositionBuffer_getDataPointer=a=>(v._unicodePositionBuffer_getDataPointer=Y.unicodePositionBuffer_getDataPointer)(a);v._unicodePositionBuffer_free=a=>(v._unicodePositionBuffer_free=Y.unicodePositionBuffer_free)(a);v._lineBreakBuffer_create=a=>(v._lineBreakBuffer_create=Y.lineBreakBuffer_create)(a);
|
||||
v._lineBreakBuffer_getDataPointer=a=>(v._lineBreakBuffer_getDataPointer=Y.lineBreakBuffer_getDataPointer)(a);v._lineBreakBuffer_free=a=>(v._lineBreakBuffer_free=Y.lineBreakBuffer_free)(a);v._paragraphBuilder_setGraphemeBreaksUtf16=(a,b)=>(v._paragraphBuilder_setGraphemeBreaksUtf16=Y.paragraphBuilder_setGraphemeBreaksUtf16)(a,b);v._paragraphBuilder_setWordBreaksUtf16=(a,b)=>(v._paragraphBuilder_setWordBreaksUtf16=Y.paragraphBuilder_setWordBreaksUtf16)(a,b);
|
||||
v._paragraphBuilder_setLineBreaksUtf16=(a,b)=>(v._paragraphBuilder_setLineBreaksUtf16=Y.paragraphBuilder_setLineBreaksUtf16)(a,b);v._paragraphStyle_create=()=>(v._paragraphStyle_create=Y.paragraphStyle_create)();v._paragraphStyle_dispose=a=>(v._paragraphStyle_dispose=Y.paragraphStyle_dispose)(a);v._paragraphStyle_setTextAlign=(a,b)=>(v._paragraphStyle_setTextAlign=Y.paragraphStyle_setTextAlign)(a,b);
|
||||
v._paragraphStyle_setTextDirection=(a,b)=>(v._paragraphStyle_setTextDirection=Y.paragraphStyle_setTextDirection)(a,b);v._paragraphStyle_setMaxLines=(a,b)=>(v._paragraphStyle_setMaxLines=Y.paragraphStyle_setMaxLines)(a,b);v._paragraphStyle_setHeight=(a,b)=>(v._paragraphStyle_setHeight=Y.paragraphStyle_setHeight)(a,b);v._paragraphStyle_setTextHeightBehavior=(a,b,c)=>(v._paragraphStyle_setTextHeightBehavior=Y.paragraphStyle_setTextHeightBehavior)(a,b,c);
|
||||
v._paragraphStyle_setEllipsis=(a,b)=>(v._paragraphStyle_setEllipsis=Y.paragraphStyle_setEllipsis)(a,b);v._paragraphStyle_setStrutStyle=(a,b)=>(v._paragraphStyle_setStrutStyle=Y.paragraphStyle_setStrutStyle)(a,b);v._paragraphStyle_setTextStyle=(a,b)=>(v._paragraphStyle_setTextStyle=Y.paragraphStyle_setTextStyle)(a,b);v._paragraphStyle_setApplyRoundingHack=(a,b)=>(v._paragraphStyle_setApplyRoundingHack=Y.paragraphStyle_setApplyRoundingHack)(a,b);v._strutStyle_create=()=>(v._strutStyle_create=Y.strutStyle_create)();
|
||||
v._strutStyle_dispose=a=>(v._strutStyle_dispose=Y.strutStyle_dispose)(a);v._strutStyle_setFontFamilies=(a,b,c)=>(v._strutStyle_setFontFamilies=Y.strutStyle_setFontFamilies)(a,b,c);v._strutStyle_setFontSize=(a,b)=>(v._strutStyle_setFontSize=Y.strutStyle_setFontSize)(a,b);v._strutStyle_setHeight=(a,b)=>(v._strutStyle_setHeight=Y.strutStyle_setHeight)(a,b);v._strutStyle_setHalfLeading=(a,b)=>(v._strutStyle_setHalfLeading=Y.strutStyle_setHalfLeading)(a,b);
|
||||
v._strutStyle_setLeading=(a,b)=>(v._strutStyle_setLeading=Y.strutStyle_setLeading)(a,b);v._strutStyle_setFontStyle=(a,b,c)=>(v._strutStyle_setFontStyle=Y.strutStyle_setFontStyle)(a,b,c);v._strutStyle_setForceStrutHeight=(a,b)=>(v._strutStyle_setForceStrutHeight=Y.strutStyle_setForceStrutHeight)(a,b);v._textStyle_create=()=>(v._textStyle_create=Y.textStyle_create)();v._textStyle_copy=a=>(v._textStyle_copy=Y.textStyle_copy)(a);v._textStyle_dispose=a=>(v._textStyle_dispose=Y.textStyle_dispose)(a);
|
||||
v._textStyle_setColor=(a,b)=>(v._textStyle_setColor=Y.textStyle_setColor)(a,b);v._textStyle_setDecoration=(a,b)=>(v._textStyle_setDecoration=Y.textStyle_setDecoration)(a,b);v._textStyle_setDecorationColor=(a,b)=>(v._textStyle_setDecorationColor=Y.textStyle_setDecorationColor)(a,b);v._textStyle_setDecorationStyle=(a,b)=>(v._textStyle_setDecorationStyle=Y.textStyle_setDecorationStyle)(a,b);
|
||||
v._textStyle_setDecorationThickness=(a,b)=>(v._textStyle_setDecorationThickness=Y.textStyle_setDecorationThickness)(a,b);v._textStyle_setFontStyle=(a,b,c)=>(v._textStyle_setFontStyle=Y.textStyle_setFontStyle)(a,b,c);v._textStyle_setTextBaseline=(a,b)=>(v._textStyle_setTextBaseline=Y.textStyle_setTextBaseline)(a,b);v._textStyle_clearFontFamilies=a=>(v._textStyle_clearFontFamilies=Y.textStyle_clearFontFamilies)(a);
|
||||
v._textStyle_addFontFamilies=(a,b,c)=>(v._textStyle_addFontFamilies=Y.textStyle_addFontFamilies)(a,b,c);v._textStyle_setFontSize=(a,b)=>(v._textStyle_setFontSize=Y.textStyle_setFontSize)(a,b);v._textStyle_setLetterSpacing=(a,b)=>(v._textStyle_setLetterSpacing=Y.textStyle_setLetterSpacing)(a,b);v._textStyle_setWordSpacing=(a,b)=>(v._textStyle_setWordSpacing=Y.textStyle_setWordSpacing)(a,b);v._textStyle_setHeight=(a,b)=>(v._textStyle_setHeight=Y.textStyle_setHeight)(a,b);
|
||||
v._textStyle_setHalfLeading=(a,b)=>(v._textStyle_setHalfLeading=Y.textStyle_setHalfLeading)(a,b);v._textStyle_setLocale=(a,b)=>(v._textStyle_setLocale=Y.textStyle_setLocale)(a,b);v._textStyle_setBackground=(a,b)=>(v._textStyle_setBackground=Y.textStyle_setBackground)(a,b);v._textStyle_setForeground=(a,b)=>(v._textStyle_setForeground=Y.textStyle_setForeground)(a,b);v._textStyle_addShadow=(a,b,c,d,f)=>(v._textStyle_addShadow=Y.textStyle_addShadow)(a,b,c,d,f);
|
||||
v._textStyle_addFontFeature=(a,b,c)=>(v._textStyle_addFontFeature=Y.textStyle_addFontFeature)(a,b,c);v._textStyle_setFontVariations=(a,b,c,d)=>(v._textStyle_setFontVariations=Y.textStyle_setFontVariations)(a,b,c,d);v._vertices_create=(a,b,c,d,f,g,l)=>(v._vertices_create=Y.vertices_create)(a,b,c,d,f,g,l);v._vertices_dispose=a=>(v._vertices_dispose=Y.vertices_dispose)(a);v._skwasm_isMultiThreaded=()=>(v._skwasm_isMultiThreaded=Y.skwasm_isMultiThreaded)();
|
||||
var ya=()=>(ya=Y.pthread_self)(),xf=a=>(xf=Y.malloc)(a),Ba=(a,b,c,d,f,g)=>(Ba=Y._emscripten_thread_init)(a,b,c,d,f,g),Ha=()=>(Ha=Y._emscripten_thread_crashed)(),bf=(a,b,c,d,f)=>(bf=Y._emscripten_run_on_main_thread_js)(a,b,c,d,f),jf=a=>(jf=Y._emscripten_thread_free_data)(a),pf=a=>(pf=Y._emscripten_thread_exit)(a),Df=(a,b)=>(Df=Y._emscripten_timeout)(a,b),zf=()=>(zf=Y._emscripten_check_mailbox)(),Z=(a,b)=>(Z=Y.setThrew)(a,b),of=(a,b)=>(of=Y.emscripten_stack_set_limits)(a,b),G=a=>(G=Y._emscripten_stack_restore)(a),
|
||||
$e=a=>($e=Y._emscripten_stack_alloc)(a),E=()=>(E=Y.emscripten_stack_get_current)();function xe(a,b,c){var d=E();try{return I.get(a)(b,c)}catch(f){G(d);if(f!==f+0)throw f;Z(1,0)}}function Ce(a,b,c){var d=E();try{I.get(a)(b,c)}catch(f){G(d);if(f!==f+0)throw f;Z(1,0)}}function we(a,b){var c=E();try{return I.get(a)(b)}catch(d){G(c);if(d!==d+0)throw d;Z(1,0)}}function De(a,b,c,d){var f=E();try{I.get(a)(b,c,d)}catch(g){G(f);if(g!==g+0)throw g;Z(1,0)}}
|
||||
function ye(a,b,c,d){var f=E();try{return I.get(a)(b,c,d)}catch(g){G(f);if(g!==g+0)throw g;Z(1,0)}}function Ee(a,b,c,d,f){var g=E();try{I.get(a)(b,c,d,f)}catch(l){G(g);if(l!==l+0)throw l;Z(1,0)}}function Fe(a,b,c,d,f,g,l,m){var p=E();try{I.get(a)(b,c,d,f,g,l,m)}catch(r){G(p);if(r!==r+0)throw r;Z(1,0)}}function Be(a,b){var c=E();try{I.get(a)(b)}catch(d){G(c);if(d!==d+0)throw d;Z(1,0)}}function Ae(a,b,c,d,f,g,l){var m=E();try{return I.get(a)(b,c,d,f,g,l)}catch(p){G(m);if(p!==p+0)throw p;Z(1,0)}}
|
||||
function ze(a,b,c,d,f){var g=E();try{return I.get(a)(b,c,d,f)}catch(l){G(g);if(l!==l+0)throw l;Z(1,0)}}v.wasmMemory=e;v.wasmExports=Y;v.stackAlloc=af;
|
||||
v.addFunction=(a,b)=>{if(!mg){mg=new WeakMap;var c=I.length;if(mg)for(var d=0;d<0+c;d++){var f=I.get(d);f&&mg.set(f,d)}}if(c=mg.get(a)||0)return c;if(ng.length)c=ng.pop();else{try{I.grow(1)}catch(m){if(!(m instanceof RangeError))throw m;throw"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.";}c=I.length-1}try{I.set(c,a)}catch(m){if(!(m instanceof TypeError))throw m;if("function"==typeof WebAssembly.Function){d=WebAssembly.Function;f={i:"i32",j:"i64",f:"f32",d:"f64",e:"externref",p:"i32"};for(var g=
|
||||
{parameters:[],results:"v"==b[0]?[]:[f[b[0]]]},l=1;l<b.length;++l)g.parameters.push(f[b[l]]);b=new d(g,a)}else{d=[1];f=b.slice(0,1);b=b.slice(1);g={i:127,p:127,j:126,f:125,d:124,e:111};d.push(96);l=b.length;128>l?d.push(l):d.push(l%128|128,l>>7);for(l=0;l<b.length;++l)d.push(g[b[l]]);"v"==f?d.push(0):d.push(1,g[f]);b=[0,97,115,109,1,0,0,0,1];f=d.length;128>f?b.push(f):b.push(f%128|128,f>>7);b.push(...d);b.push(2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);b=new WebAssembly.Module(new Uint8Array(b));b=(new WebAssembly.Instance(b,
|
||||
{e:{f:a}})).exports.f}I.set(c,b)}mg.set(a,c);return c};var wg,xg;Ma=function yg(){wg||zg();wg||(Ma=yg)};function zg(){if(!(0<z))if(w)ia(v),w||nf(Ja),startWorker(v);else{if(!xg&&(xg=1,nf(Ia),0<z))return;wg||(wg=1,v.calledRun=1,sa||(w||nf(Ja),ia(v),w||nf(Ka)))}}zg();moduleRtn=ka;
|
||||
|
||||
|
||||
return moduleRtn;
|
||||
}
|
||||
);
|
||||
})();
|
||||
export default skwasm;
|
||||
var isPthread = globalThis.self?.name?.startsWith('em-pthread');
|
||||
// When running as a pthread, construct a new instance on startup
|
||||
isPthread && skwasm();
|
||||
12099
internal/form_generator/templates/canvaskit/skwasm.js.symbols
Normal file
BIN
internal/form_generator/templates/canvaskit/skwasm.wasm
Normal file
134
internal/form_generator/templates/canvaskit/skwasm_st.js
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
var skwasm_st = (() => {
|
||||
var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined;
|
||||
|
||||
return (
|
||||
function(moduleArg = {}) {
|
||||
var moduleRtn;
|
||||
|
||||
function d(){g.buffer!=k.buffer&&n();return k}function q(){g.buffer!=k.buffer&&n();return aa}function r(){g.buffer!=k.buffer&&n();return ba}function t(){g.buffer!=k.buffer&&n();return ca}function u(){g.buffer!=k.buffer&&n();return da}var w=moduleArg,ea,fa,ha=new Promise((a,b)=>{ea=a;fa=b}),ia="object"==typeof window,ja="function"==typeof importScripts,ka=Object.assign({},w),x="",la,ma;
|
||||
if(ia||ja)ja?x=self.location.href:"undefined"!=typeof document&&document.currentScript&&(x=document.currentScript.src),_scriptName&&(x=_scriptName),x.startsWith("blob:")?x="":x=x.substr(0,x.replace(/[?#].*/,"").lastIndexOf("/")+1),ja&&(ma=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),la=a=>fetch(a,{credentials:"same-origin"}).then(b=>b.ok?b.arrayBuffer():Promise.reject(Error(b.status+" : "+b.url)));
|
||||
var na=console.log.bind(console),y=console.error.bind(console);Object.assign(w,ka);ka=null;var g,oa=!1,pa,k,aa,qa,ra,ba,ca,da;function n(){var a=g.buffer;k=new Int8Array(a);qa=new Int16Array(a);aa=new Uint8Array(a);ra=new Uint16Array(a);ba=new Int32Array(a);ca=new Uint32Array(a);da=new Float32Array(a);new Float64Array(a)}var sa=[],ta=[],ua=[],z=0,va=null,A=null;
|
||||
function wa(a){a="Aborted("+a+")";y(a);oa=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");fa(a);throw a;}var xa=a=>a.startsWith("data:application/octet-stream;base64,"),ya;function za(a){return la(a).then(b=>new Uint8Array(b),()=>{if(ma)var b=ma(a);else throw"both async and sync fetching of the wasm failed";return b})}function Aa(a,b,c){return za(a).then(e=>WebAssembly.instantiate(e,b)).then(c,e=>{y(`failed to asynchronously prepare wasm: ${e}`);wa(e)})}
|
||||
function Ba(a,b){var c=ya;return"function"!=typeof WebAssembly.instantiateStreaming||xa(c)||"function"!=typeof fetch?Aa(c,a,b):fetch(c,{credentials:"same-origin"}).then(e=>WebAssembly.instantiateStreaming(e,a).then(b,function(f){y(`wasm streaming compile failed: ${f}`);y("falling back to ArrayBuffer instantiation");return Aa(c,a,b)}))}function Ca(a){this.name="ExitStatus";this.message=`Program terminated with exit(${a})`;this.status=a}var Da=a=>{a.forEach(b=>b(w))},Ea=w.noExitRuntime||!0;
|
||||
class Fa{constructor(a){this.s=a-24}}
|
||||
var Ga=0,Ha=0,Ia="undefined"!=typeof TextDecoder?new TextDecoder:void 0,Ja=(a,b=0,c=NaN)=>{var e=b+c;for(c=b;a[c]&&!(c>=e);)++c;if(16<c-b&&a.buffer&&Ia)return Ia.decode(a.slice(b,c));for(e="";b<c;){var f=a[b++];if(f&128){var h=a[b++]&63;if(192==(f&224))e+=String.fromCharCode((f&31)<<6|h);else{var l=a[b++]&63;f=224==(f&240)?(f&15)<<12|h<<6|l:(f&7)<<18|h<<12|l<<6|a[b++]&63;65536>f?e+=String.fromCharCode(f):(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else e+=String.fromCharCode(f)}return e},
|
||||
Ka=(a,b)=>a?Ja(q(),a,b):"",B={},La=a=>{if(!(a instanceof Ca||"unwind"==a))throw a;},Ma=0,Na=a=>{pa=a;Ea||0<Ma||(oa=!0);throw new Ca(a);},Oa=a=>{if(!oa)try{if(a(),!(Ea||0<Ma))try{pa=a=pa,Na(a)}catch(b){La(b)}}catch(b){La(b)}},C=(a,b,c)=>{var e=q();if(0<c){var f=b;c=b+c-1;for(var h=0;h<a.length;++h){var l=a.charCodeAt(h);if(55296<=l&&57343>=l){var m=a.charCodeAt(++h);l=65536+((l&1023)<<10)|m&1023}if(127>=l){if(b>=c)break;e[b++]=l}else{if(2047>=l){if(b+1>=c)break;e[b++]=192|l>>6}else{if(65535>=l){if(b+
|
||||
2>=c)break;e[b++]=224|l>>12}else{if(b+3>=c)break;e[b++]=240|l>>18;e[b++]=128|l>>12&63}e[b++]=128|l>>6&63}e[b++]=128|l&63}}e[b]=0;a=b-f}else a=0;return a},D,Pa=a=>{var b=a.getExtension("ANGLE_instanced_arrays");b&&(a.vertexAttribDivisor=(c,e)=>b.vertexAttribDivisorANGLE(c,e),a.drawArraysInstanced=(c,e,f,h)=>b.drawArraysInstancedANGLE(c,e,f,h),a.drawElementsInstanced=(c,e,f,h,l)=>b.drawElementsInstancedANGLE(c,e,f,h,l))},Qa=a=>{var b=a.getExtension("OES_vertex_array_object");b&&(a.createVertexArray=
|
||||
()=>b.createVertexArrayOES(),a.deleteVertexArray=c=>b.deleteVertexArrayOES(c),a.bindVertexArray=c=>b.bindVertexArrayOES(c),a.isVertexArray=c=>b.isVertexArrayOES(c))},Ra=a=>{var b=a.getExtension("WEBGL_draw_buffers");b&&(a.drawBuffers=(c,e)=>b.drawBuffersWEBGL(c,e))},Sa=a=>{a.H=a.getExtension("WEBGL_draw_instanced_base_vertex_base_instance")},Ta=a=>{a.K=a.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance")},Ua=a=>{var b="ANGLE_instanced_arrays EXT_blend_minmax EXT_disjoint_timer_query EXT_frag_depth EXT_shader_texture_lod EXT_sRGB OES_element_index_uint OES_fbo_render_mipmap OES_standard_derivatives OES_texture_float OES_texture_half_float OES_texture_half_float_linear OES_vertex_array_object WEBGL_color_buffer_float WEBGL_depth_texture WEBGL_draw_buffers EXT_color_buffer_float EXT_conservative_depth EXT_disjoint_timer_query_webgl2 EXT_texture_norm16 NV_shader_noperspective_interpolation WEBGL_clip_cull_distance EXT_clip_control EXT_color_buffer_half_float EXT_depth_clamp EXT_float_blend EXT_polygon_offset_clamp EXT_texture_compression_bptc EXT_texture_compression_rgtc EXT_texture_filter_anisotropic KHR_parallel_shader_compile OES_texture_float_linear WEBGL_blend_func_extended WEBGL_compressed_texture_astc WEBGL_compressed_texture_etc WEBGL_compressed_texture_etc1 WEBGL_compressed_texture_s3tc WEBGL_compressed_texture_s3tc_srgb WEBGL_debug_renderer_info WEBGL_debug_shaders WEBGL_lose_context WEBGL_multi_draw WEBGL_polygon_mode".split(" ");
|
||||
return(a.getSupportedExtensions()||[]).filter(c=>b.includes(c))},Va=1,Wa=[],E=[],Xa=[],F=[],G=[],H=[],Ya=[],Za=[],I=[],J=[],K=[],$a={},ab={},bb=4,cb=0,L=a=>{for(var b=Va++,c=a.length;c<b;c++)a[c]=null;return b},N=(a,b,c,e)=>{for(var f=0;f<a;f++){var h=D[c](),l=h&&L(e);h?(h.name=l,e[l]=h):M||=1282;r()[b+4*f>>2]=l}},eb=a=>{var b={J:2,alpha:!0,depth:!0,stencil:!0,antialias:!1,premultipliedAlpha:!0,preserveDrawingBuffer:!1,powerPreference:"default",failIfMajorPerformanceCaveat:!1,I:!0};a.s||(a.s=a.getContext,
|
||||
a.getContext=function(e,f){f=a.s(e,f);return"webgl"==e==f instanceof WebGLRenderingContext?f:null});var c=1<b.J?a.getContext("webgl2",b):a.getContext("webgl",b);return c?db(c,b):0},db=(a,b)=>{var c=L(Za),e={handle:c,attributes:b,version:b.J,v:a};a.canvas&&(a.canvas.Z=e);Za[c]=e;("undefined"==typeof b.I||b.I)&&fb(e);return c},fb=a=>{a||=O;if(!a.S){a.S=!0;var b=a.v;b.T=b.getExtension("WEBGL_multi_draw");b.P=b.getExtension("EXT_polygon_offset_clamp");b.O=b.getExtension("EXT_clip_control");b.Y=b.getExtension("WEBGL_polygon_mode");
|
||||
Pa(b);Qa(b);Ra(b);Sa(b);Ta(b);2<=a.version&&(b.g=b.getExtension("EXT_disjoint_timer_query_webgl2"));if(2>a.version||!b.g)b.g=b.getExtension("EXT_disjoint_timer_query");Ua(b).forEach(c=>{c.includes("lose_context")||c.includes("debug")||b.getExtension(c)})}},M,O,gb=a=>{D.bindVertexArray(Ya[a])},hb=(a,b)=>{for(var c=0;c<a;c++){var e=r()[b+4*c>>2],f=G[e];f&&(D.deleteTexture(f),f.name=0,G[e]=null)}},ib=(a,b)=>{for(var c=0;c<a;c++){var e=r()[b+4*c>>2];D.deleteVertexArray(Ya[e]);Ya[e]=null}},jb=[],kb=(a,
|
||||
b)=>{N(a,b,"createVertexArray",Ya)},lb=(a,b)=>{t()[a>>2]=b;var c=t()[a>>2];t()[a+4>>2]=(b-c)/4294967296};function mb(){var a=Ua(D);return a=a.concat(a.map(b=>"GL_"+b))}
|
||||
var nb=(a,b,c)=>{if(b){var e=void 0;switch(a){case 36346:e=1;break;case 36344:0!=c&&1!=c&&(M||=1280);return;case 34814:case 36345:e=0;break;case 34466:var f=D.getParameter(34467);e=f?f.length:0;break;case 33309:if(2>O.version){M||=1282;return}e=mb().length;break;case 33307:case 33308:if(2>O.version){M||=1280;return}e=33307==a?3:0}if(void 0===e)switch(f=D.getParameter(a),typeof f){case "number":e=f;break;case "boolean":e=f?1:0;break;case "string":M||=1280;return;case "object":if(null===f)switch(a){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:e=
|
||||
0;break;default:M||=1280;return}else{if(f instanceof Float32Array||f instanceof Uint32Array||f instanceof Int32Array||f instanceof Array){for(a=0;a<f.length;++a)switch(c){case 0:r()[b+4*a>>2]=f[a];break;case 2:u()[b+4*a>>2]=f[a];break;case 4:d()[b+a]=f[a]?1:0}return}try{e=f.name|0}catch(h){M||=1280;y(`GL_INVALID_ENUM in glGet${c}v: Unknown object returned from WebGL getParameter(${a})! (error: ${h})`);return}}break;default:M||=1280;y(`GL_INVALID_ENUM in glGet${c}v: Native code calling glGet${c}v(${a}) and it returns ${f} of type ${typeof f}!`);
|
||||
return}switch(c){case 1:lb(b,e);break;case 0:r()[b>>2]=e;break;case 2:u()[b>>2]=e;break;case 4:d()[b]=e?1:0}}else M||=1281},ob=(a,b)=>nb(a,b,0),pb=(a,b,c)=>{if(c){a=I[a];b=2>O.version?D.g.getQueryObjectEXT(a,b):D.getQueryParameter(a,b);var e;"boolean"==typeof b?e=b?1:0:e=b;lb(c,e)}else M||=1281},rb=a=>{for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);127>=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++c):b+=3}b+=1;(c=qb(b))&&C(a,c,b);return c},sb=a=>{var b=$a[a];if(!b){switch(a){case 7939:b=rb(mb().join(" "));
|
||||
break;case 7936:case 7937:case 37445:case 37446:(b=D.getParameter(a))||(M||=1280);b=b?rb(b):0;break;case 7938:b=D.getParameter(7938);var c=`OpenGL ES 2.0 (${b})`;2<=O.version&&(c=`OpenGL ES 3.0 (${b})`);b=rb(c);break;case 35724:b=D.getParameter(35724);c=b.match(/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/);null!==c&&(3==c[1].length&&(c[1]+="0"),b=`OpenGL ES GLSL ES ${c[1]} (${b})`);b=rb(b);break;default:M||=1280}$a[a]=b}return b},tb=(a,b)=>{if(2>O.version)return M||=1282,0;var c=ab[a];if(c)return 0>
|
||||
b||b>=c.length?(M||=1281,0):c[b];switch(a){case 7939:return c=mb().map(rb),c=ab[a]=c,0>b||b>=c.length?(M||=1281,0):c[b];default:return M||=1280,0}},ub=a=>"]"==a.slice(-1)&&a.lastIndexOf("["),vb=a=>{a-=5120;0==a?a=d():1==a?a=q():2==a?(g.buffer!=k.buffer&&n(),a=qa):4==a?a=r():6==a?a=u():5==a||28922==a||28520==a||30779==a||30782==a?a=t():(g.buffer!=k.buffer&&n(),a=ra);return a},wb=(a,b,c,e,f)=>{a=vb(a);b=e*((cb||c)*({5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4}[b-6402]||1)*a.BYTES_PER_ELEMENT+
|
||||
bb-1&-bb);return a.subarray(f>>>31-Math.clz32(a.BYTES_PER_ELEMENT),f+b>>>31-Math.clz32(a.BYTES_PER_ELEMENT))},P=a=>{var b=D.N;if(b){var c=b.u[a];"number"==typeof c&&(b.u[a]=c=D.getUniformLocation(b,b.L[a]+(0<c?`[${c}]`:"")));return c}M||=1282},Q=[],xb=[],yb={},Ab=()=>{if(!zb){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:"./this.program"},b;for(b in yb)void 0===
|
||||
yb[b]?delete a[b]:a[b]=yb[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);zb=c}return zb},zb,Bb=[null,[],[]];function Cb(){}function Db(){}function R(){}function Eb(){}function Fb(){}function Gb(){}function Hb(){}function Ib(){}function Jb(){}function Kb(){}function Lb(){}function Mb(){}function Nb(){}function Ob(){}function Pb(){}function Qb(){}var S,U,Rb=[],Tb=a=>Sb(a);w.stackAlloc=Tb;for(var V=0;32>V;++V)jb.push(Array(V));var Ub=new Float32Array(288);for(V=0;288>=V;++V)Q[V]=Ub.subarray(0,V);
|
||||
var Vb=new Int32Array(288);for(V=0;288>=V;++V)xb[V]=Vb.subarray(0,V);
|
||||
(function(){const a=new Map,b=new Map;Qb=function(c,e,f){R({m:"setAssociatedObject",F:e,object:f})};Mb=function(c){return b.get(c)};Fb=function(){Cb(function(c){var e=c.m;if(e)switch(e){case "renderPictures":Wb(c.h,c.V,c.U,c.l,Db());break;case "onRenderComplete":Xb(c.h,c.l,{imageBitmaps:c.R,rasterStartMilliseconds:c.X,rasterEndMilliseconds:c.W});break;case "setAssociatedObject":b.set(c.F,c.object);break;case "disposeAssociatedObject":c=c.F;e=b.get(c);e.close&&e.close();b.delete(c);break;case "disposeSurface":Yb(c.h);
|
||||
break;case "rasterizeImage":Zb(c.h,c.image,c.format,c.l);break;case "onRasterizeComplete":$b(c.h,c.data,c.l);break;default:console.warn(`unrecognized skwasm message: ${e}`)}})};Kb=function(c,e,f,h,l){R({m:"renderPictures",h:e,V:f,U:h,l})};Hb=function(c,e){c=new OffscreenCanvas(c,e);e=eb(c);a.set(e,c);return e};Ob=function(c,e,f){c=a.get(c);c.width=e;c.height=f};Eb=function(c,e,f,h){h||=[];c=a.get(c);h.push(createImageBitmap(c,0,0,e,f));return h};Pb=async function(c,e,f,h){e=e?await Promise.all(e):
|
||||
[];R({m:"onRenderComplete",h:c,l:h,R:e,X:f,W:Db()},[...e])};Gb=function(c,e,f){const h=O.v,l=h.createTexture();h.bindTexture(h.TEXTURE_2D,l);h.pixelStorei(h.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0);h.texImage2D(h.TEXTURE_2D,0,h.RGBA,e,f,0,h.RGBA,h.UNSIGNED_BYTE,c);h.pixelStorei(h.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);h.bindTexture(h.TEXTURE_2D,null);c=L(G);G[c]=l;return c};Lb=function(c,e){R({m:"disposeAssociatedObject",F:e})};Ib=function(c,e){R({m:"disposeSurface",h:e})};Jb=function(c,e,f,h,l){R({m:"rasterizeImage",
|
||||
h:e,image:f,format:h,l})};Nb=function(c,e,f){R({m:"onRasterizeComplete",h:c,data:e,l:f})}})();(function(){let a;Cb=function(b){a=b};Db=function(){return performance.now()};R=function(b){queueMicrotask(()=>{a(b)})}})();
|
||||
var lc={__cxa_throw:(a,b,c)=>{var e=new Fa(a);t()[e.s+16>>2]=0;t()[e.s+4>>2]=b;t()[e.s+8>>2]=c;Ga=a;Ha++;throw Ga;},__syscall_fcntl64:function(){return 0},__syscall_fstat64:()=>{},__syscall_ioctl:function(){return 0},__syscall_openat:function(){},_abort_js:()=>{wa("")},_emscripten_get_now_is_monotonic:()=>1,_emscripten_runtime_keepalive_clear:()=>{Ea=!1;Ma=0},_emscripten_throw_longjmp:()=>{throw Infinity;},_mmap_js:function(){return-52},_munmap_js:function(){},_setitimer_js:(a,b)=>{B[a]&&(clearTimeout(B[a].id),
|
||||
delete B[a]);if(!b)return 0;var c=setTimeout(()=>{delete B[a];Oa(()=>ac(a,performance.now()))},b);B[a]={id:c,aa:b};return 0},_tzset_js:(a,b,c,e)=>{var f=(new Date).getFullYear(),h=(new Date(f,0,1)).getTimezoneOffset();f=(new Date(f,6,1)).getTimezoneOffset();var l=Math.max(h,f);t()[a>>2]=60*l;r()[b>>2]=Number(h!=f);b=m=>{var p=Math.abs(m);return`UTC${0<=m?"-":"+"}${String(Math.floor(p/60)).padStart(2,"0")}${String(p%60).padStart(2,"0")}`};a=b(h);b=b(f);f<h?(C(a,c,17),C(b,e,17)):(C(a,e,17),C(b,c,17))},
|
||||
emscripten_get_now:()=>performance.now(),emscripten_glActiveTexture:a=>D.activeTexture(a),emscripten_glAttachShader:(a,b)=>{D.attachShader(E[a],H[b])},emscripten_glBeginQuery:(a,b)=>{D.beginQuery(a,I[b])},emscripten_glBeginQueryEXT:(a,b)=>{D.g.beginQueryEXT(a,I[b])},emscripten_glBindAttribLocation:(a,b,c)=>{D.bindAttribLocation(E[a],b,Ka(c))},emscripten_glBindBuffer:(a,b)=>{35051==a?D.D=b:35052==a&&(D.o=b);D.bindBuffer(a,Wa[b])},emscripten_glBindFramebuffer:(a,b)=>{D.bindFramebuffer(a,Xa[b])},emscripten_glBindRenderbuffer:(a,
|
||||
b)=>{D.bindRenderbuffer(a,F[b])},emscripten_glBindSampler:(a,b)=>{D.bindSampler(a,J[b])},emscripten_glBindTexture:(a,b)=>{D.bindTexture(a,G[b])},emscripten_glBindVertexArray:gb,emscripten_glBindVertexArrayOES:gb,emscripten_glBlendColor:(a,b,c,e)=>D.blendColor(a,b,c,e),emscripten_glBlendEquation:a=>D.blendEquation(a),emscripten_glBlendFunc:(a,b)=>D.blendFunc(a,b),emscripten_glBlitFramebuffer:(a,b,c,e,f,h,l,m,p,v)=>D.blitFramebuffer(a,b,c,e,f,h,l,m,p,v),emscripten_glBufferData:(a,b,c,e)=>{2<=O.version?
|
||||
c&&b?D.bufferData(a,q(),e,c,b):D.bufferData(a,b,e):D.bufferData(a,c?q().subarray(c,c+b):b,e)},emscripten_glBufferSubData:(a,b,c,e)=>{2<=O.version?c&&D.bufferSubData(a,b,q(),e,c):D.bufferSubData(a,b,q().subarray(e,e+c))},emscripten_glCheckFramebufferStatus:a=>D.checkFramebufferStatus(a),emscripten_glClear:a=>D.clear(a),emscripten_glClearColor:(a,b,c,e)=>D.clearColor(a,b,c,e),emscripten_glClearStencil:a=>D.clearStencil(a),emscripten_glClientWaitSync:(a,b,c,e)=>D.clientWaitSync(K[a],b,(c>>>0)+4294967296*
|
||||
e),emscripten_glColorMask:(a,b,c,e)=>{D.colorMask(!!a,!!b,!!c,!!e)},emscripten_glCompileShader:a=>{D.compileShader(H[a])},emscripten_glCompressedTexImage2D:(a,b,c,e,f,h,l,m)=>{2<=O.version?D.o||!l?D.compressedTexImage2D(a,b,c,e,f,h,l,m):D.compressedTexImage2D(a,b,c,e,f,h,q(),m,l):D.compressedTexImage2D(a,b,c,e,f,h,q().subarray(m,m+l))},emscripten_glCompressedTexSubImage2D:(a,b,c,e,f,h,l,m,p)=>{2<=O.version?D.o||!m?D.compressedTexSubImage2D(a,b,c,e,f,h,l,m,p):D.compressedTexSubImage2D(a,b,c,e,f,h,
|
||||
l,q(),p,m):D.compressedTexSubImage2D(a,b,c,e,f,h,l,q().subarray(p,p+m))},emscripten_glCopyBufferSubData:(a,b,c,e,f)=>D.copyBufferSubData(a,b,c,e,f),emscripten_glCopyTexSubImage2D:(a,b,c,e,f,h,l,m)=>D.copyTexSubImage2D(a,b,c,e,f,h,l,m),emscripten_glCreateProgram:()=>{var a=L(E),b=D.createProgram();b.name=a;b.C=b.A=b.B=0;b.G=1;E[a]=b;return a},emscripten_glCreateShader:a=>{var b=L(H);H[b]=D.createShader(a);return b},emscripten_glCullFace:a=>D.cullFace(a),emscripten_glDeleteBuffers:(a,b)=>{for(var c=
|
||||
0;c<a;c++){var e=r()[b+4*c>>2],f=Wa[e];f&&(D.deleteBuffer(f),f.name=0,Wa[e]=null,e==D.D&&(D.D=0),e==D.o&&(D.o=0))}},emscripten_glDeleteFramebuffers:(a,b)=>{for(var c=0;c<a;++c){var e=r()[b+4*c>>2],f=Xa[e];f&&(D.deleteFramebuffer(f),f.name=0,Xa[e]=null)}},emscripten_glDeleteProgram:a=>{if(a){var b=E[a];b?(D.deleteProgram(b),b.name=0,E[a]=null):M||=1281}},emscripten_glDeleteQueries:(a,b)=>{for(var c=0;c<a;c++){var e=r()[b+4*c>>2],f=I[e];f&&(D.deleteQuery(f),I[e]=null)}},emscripten_glDeleteQueriesEXT:(a,
|
||||
b)=>{for(var c=0;c<a;c++){var e=r()[b+4*c>>2],f=I[e];f&&(D.g.deleteQueryEXT(f),I[e]=null)}},emscripten_glDeleteRenderbuffers:(a,b)=>{for(var c=0;c<a;c++){var e=r()[b+4*c>>2],f=F[e];f&&(D.deleteRenderbuffer(f),f.name=0,F[e]=null)}},emscripten_glDeleteSamplers:(a,b)=>{for(var c=0;c<a;c++){var e=r()[b+4*c>>2],f=J[e];f&&(D.deleteSampler(f),f.name=0,J[e]=null)}},emscripten_glDeleteShader:a=>{if(a){var b=H[a];b?(D.deleteShader(b),H[a]=null):M||=1281}},emscripten_glDeleteSync:a=>{if(a){var b=K[a];b?(D.deleteSync(b),
|
||||
b.name=0,K[a]=null):M||=1281}},emscripten_glDeleteTextures:hb,emscripten_glDeleteVertexArrays:ib,emscripten_glDeleteVertexArraysOES:ib,emscripten_glDepthMask:a=>{D.depthMask(!!a)},emscripten_glDisable:a=>D.disable(a),emscripten_glDisableVertexAttribArray:a=>{D.disableVertexAttribArray(a)},emscripten_glDrawArrays:(a,b,c)=>{D.drawArrays(a,b,c)},emscripten_glDrawArraysInstanced:(a,b,c,e)=>{D.drawArraysInstanced(a,b,c,e)},emscripten_glDrawArraysInstancedBaseInstanceWEBGL:(a,b,c,e,f)=>{D.H.drawArraysInstancedBaseInstanceWEBGL(a,
|
||||
b,c,e,f)},emscripten_glDrawBuffers:(a,b)=>{for(var c=jb[a],e=0;e<a;e++)c[e]=r()[b+4*e>>2];D.drawBuffers(c)},emscripten_glDrawElements:(a,b,c,e)=>{D.drawElements(a,b,c,e)},emscripten_glDrawElementsInstanced:(a,b,c,e,f)=>{D.drawElementsInstanced(a,b,c,e,f)},emscripten_glDrawElementsInstancedBaseVertexBaseInstanceWEBGL:(a,b,c,e,f,h,l)=>{D.H.drawElementsInstancedBaseVertexBaseInstanceWEBGL(a,b,c,e,f,h,l)},emscripten_glDrawRangeElements:(a,b,c,e,f,h)=>{D.drawElements(a,e,f,h)},emscripten_glEnable:a=>D.enable(a),
|
||||
emscripten_glEnableVertexAttribArray:a=>{D.enableVertexAttribArray(a)},emscripten_glEndQuery:a=>D.endQuery(a),emscripten_glEndQueryEXT:a=>{D.g.endQueryEXT(a)},emscripten_glFenceSync:(a,b)=>(a=D.fenceSync(a,b))?(b=L(K),a.name=b,K[b]=a,b):0,emscripten_glFinish:()=>D.finish(),emscripten_glFlush:()=>D.flush(),emscripten_glFramebufferRenderbuffer:(a,b,c,e)=>{D.framebufferRenderbuffer(a,b,c,F[e])},emscripten_glFramebufferTexture2D:(a,b,c,e,f)=>{D.framebufferTexture2D(a,b,c,G[e],f)},emscripten_glFrontFace:a=>
|
||||
D.frontFace(a),emscripten_glGenBuffers:(a,b)=>{N(a,b,"createBuffer",Wa)},emscripten_glGenFramebuffers:(a,b)=>{N(a,b,"createFramebuffer",Xa)},emscripten_glGenQueries:(a,b)=>{N(a,b,"createQuery",I)},emscripten_glGenQueriesEXT:(a,b)=>{for(var c=0;c<a;c++){var e=D.g.createQueryEXT();if(!e){for(M||=1282;c<a;)r()[b+4*c++>>2]=0;break}var f=L(I);e.name=f;I[f]=e;r()[b+4*c>>2]=f}},emscripten_glGenRenderbuffers:(a,b)=>{N(a,b,"createRenderbuffer",F)},emscripten_glGenSamplers:(a,b)=>{N(a,b,"createSampler",J)},
|
||||
emscripten_glGenTextures:(a,b)=>{N(a,b,"createTexture",G)},emscripten_glGenVertexArrays:kb,emscripten_glGenVertexArraysOES:kb,emscripten_glGenerateMipmap:a=>D.generateMipmap(a),emscripten_glGetBufferParameteriv:(a,b,c)=>{c?r()[c>>2]=D.getBufferParameter(a,b):M||=1281},emscripten_glGetError:()=>{var a=D.getError()||M;M=0;return a},emscripten_glGetFloatv:(a,b)=>nb(a,b,2),emscripten_glGetFramebufferAttachmentParameteriv:(a,b,c,e)=>{a=D.getFramebufferAttachmentParameter(a,b,c);if(a instanceof WebGLRenderbuffer||
|
||||
a instanceof WebGLTexture)a=a.name|0;r()[e>>2]=a},emscripten_glGetIntegerv:ob,emscripten_glGetProgramInfoLog:(a,b,c,e)=>{a=D.getProgramInfoLog(E[a]);null===a&&(a="(unknown error)");b=0<b&&e?C(a,e,b):0;c&&(r()[c>>2]=b)},emscripten_glGetProgramiv:(a,b,c)=>{if(c)if(a>=Va)M||=1281;else if(a=E[a],35716==b)a=D.getProgramInfoLog(a),null===a&&(a="(unknown error)"),r()[c>>2]=a.length+1;else if(35719==b){if(!a.C){var e=D.getProgramParameter(a,35718);for(b=0;b<e;++b)a.C=Math.max(a.C,D.getActiveUniform(a,b).name.length+
|
||||
1)}r()[c>>2]=a.C}else if(35722==b){if(!a.A)for(e=D.getProgramParameter(a,35721),b=0;b<e;++b)a.A=Math.max(a.A,D.getActiveAttrib(a,b).name.length+1);r()[c>>2]=a.A}else if(35381==b){if(!a.B)for(e=D.getProgramParameter(a,35382),b=0;b<e;++b)a.B=Math.max(a.B,D.getActiveUniformBlockName(a,b).length+1);r()[c>>2]=a.B}else r()[c>>2]=D.getProgramParameter(a,b);else M||=1281},emscripten_glGetQueryObjecti64vEXT:pb,emscripten_glGetQueryObjectui64vEXT:pb,emscripten_glGetQueryObjectuiv:(a,b,c)=>{if(c){a=D.getQueryParameter(I[a],
|
||||
b);var e;"boolean"==typeof a?e=a?1:0:e=a;r()[c>>2]=e}else M||=1281},emscripten_glGetQueryObjectuivEXT:(a,b,c)=>{if(c){a=D.g.getQueryObjectEXT(I[a],b);var e;"boolean"==typeof a?e=a?1:0:e=a;r()[c>>2]=e}else M||=1281},emscripten_glGetQueryiv:(a,b,c)=>{c?r()[c>>2]=D.getQuery(a,b):M||=1281},emscripten_glGetQueryivEXT:(a,b,c)=>{c?r()[c>>2]=D.g.getQueryEXT(a,b):M||=1281},emscripten_glGetRenderbufferParameteriv:(a,b,c)=>{c?r()[c>>2]=D.getRenderbufferParameter(a,b):M||=1281},emscripten_glGetShaderInfoLog:(a,
|
||||
b,c,e)=>{a=D.getShaderInfoLog(H[a]);null===a&&(a="(unknown error)");b=0<b&&e?C(a,e,b):0;c&&(r()[c>>2]=b)},emscripten_glGetShaderPrecisionFormat:(a,b,c,e)=>{a=D.getShaderPrecisionFormat(a,b);r()[c>>2]=a.rangeMin;r()[c+4>>2]=a.rangeMax;r()[e>>2]=a.precision},emscripten_glGetShaderiv:(a,b,c)=>{c?35716==b?(a=D.getShaderInfoLog(H[a]),null===a&&(a="(unknown error)"),a=a?a.length+1:0,r()[c>>2]=a):35720==b?(a=(a=D.getShaderSource(H[a]))?a.length+1:0,r()[c>>2]=a):r()[c>>2]=D.getShaderParameter(H[a],b):M||=
|
||||
1281},emscripten_glGetString:sb,emscripten_glGetStringi:tb,emscripten_glGetUniformLocation:(a,b)=>{b=Ka(b);if(a=E[a]){var c=a,e=c.u,f=c.M,h;if(!e){c.u=e={};c.L={};var l=D.getProgramParameter(c,35718);for(h=0;h<l;++h){var m=D.getActiveUniform(c,h);var p=m.name;m=m.size;var v=ub(p);v=0<v?p.slice(0,v):p;var T=c.G;c.G+=m;f[v]=[m,T];for(p=0;p<m;++p)e[T]=p,c.L[T++]=v}}c=a.u;e=0;f=b;h=ub(b);0<h&&(e=parseInt(b.slice(h+1))>>>0,f=b.slice(0,h));if((f=a.M[f])&&e<f[0]&&(e+=f[1],c[e]=c[e]||D.getUniformLocation(a,
|
||||
b)))return e}else M||=1281;return-1},emscripten_glInvalidateFramebuffer:(a,b,c)=>{for(var e=jb[b],f=0;f<b;f++)e[f]=r()[c+4*f>>2];D.invalidateFramebuffer(a,e)},emscripten_glInvalidateSubFramebuffer:(a,b,c,e,f,h,l)=>{for(var m=jb[b],p=0;p<b;p++)m[p]=r()[c+4*p>>2];D.invalidateSubFramebuffer(a,m,e,f,h,l)},emscripten_glIsSync:a=>D.isSync(K[a]),emscripten_glIsTexture:a=>(a=G[a])?D.isTexture(a):0,emscripten_glLineWidth:a=>D.lineWidth(a),emscripten_glLinkProgram:a=>{a=E[a];D.linkProgram(a);a.u=0;a.M={}},
|
||||
emscripten_glMultiDrawArraysInstancedBaseInstanceWEBGL:(a,b,c,e,f,h)=>{D.K.multiDrawArraysInstancedBaseInstanceWEBGL(a,r(),b>>2,r(),c>>2,r(),e>>2,t(),f>>2,h)},emscripten_glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL:(a,b,c,e,f,h,l,m)=>{D.K.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(a,r(),b>>2,c,r(),e>>2,r(),f>>2,r(),h>>2,t(),l>>2,m)},emscripten_glPixelStorei:(a,b)=>{3317==a?bb=b:3314==a&&(cb=b);D.pixelStorei(a,b)},emscripten_glQueryCounterEXT:(a,b)=>{D.g.queryCounterEXT(I[a],
|
||||
b)},emscripten_glReadBuffer:a=>D.readBuffer(a),emscripten_glReadPixels:(a,b,c,e,f,h,l)=>{if(2<=O.version)if(D.D)D.readPixels(a,b,c,e,f,h,l);else{var m=vb(h);l>>>=31-Math.clz32(m.BYTES_PER_ELEMENT);D.readPixels(a,b,c,e,f,h,m,l)}else(m=wb(h,f,c,e,l))?D.readPixels(a,b,c,e,f,h,m):M||=1280},emscripten_glRenderbufferStorage:(a,b,c,e)=>D.renderbufferStorage(a,b,c,e),emscripten_glRenderbufferStorageMultisample:(a,b,c,e,f)=>D.renderbufferStorageMultisample(a,b,c,e,f),emscripten_glSamplerParameterf:(a,b,c)=>
|
||||
{D.samplerParameterf(J[a],b,c)},emscripten_glSamplerParameteri:(a,b,c)=>{D.samplerParameteri(J[a],b,c)},emscripten_glSamplerParameteriv:(a,b,c)=>{c=r()[c>>2];D.samplerParameteri(J[a],b,c)},emscripten_glScissor:(a,b,c,e)=>D.scissor(a,b,c,e),emscripten_glShaderSource:(a,b,c,e)=>{for(var f="",h=0;h<b;++h){var l=e?t()[e+4*h>>2]:void 0;f+=Ka(t()[c+4*h>>2],l)}D.shaderSource(H[a],f)},emscripten_glStencilFunc:(a,b,c)=>D.stencilFunc(a,b,c),emscripten_glStencilFuncSeparate:(a,b,c,e)=>D.stencilFuncSeparate(a,
|
||||
b,c,e),emscripten_glStencilMask:a=>D.stencilMask(a),emscripten_glStencilMaskSeparate:(a,b)=>D.stencilMaskSeparate(a,b),emscripten_glStencilOp:(a,b,c)=>D.stencilOp(a,b,c),emscripten_glStencilOpSeparate:(a,b,c,e)=>D.stencilOpSeparate(a,b,c,e),emscripten_glTexImage2D:(a,b,c,e,f,h,l,m,p)=>{if(2<=O.version){if(D.o){D.texImage2D(a,b,c,e,f,h,l,m,p);return}if(p){var v=vb(m);p>>>=31-Math.clz32(v.BYTES_PER_ELEMENT);D.texImage2D(a,b,c,e,f,h,l,m,v,p);return}}v=p?wb(m,l,e,f,p):null;D.texImage2D(a,b,c,e,f,h,l,
|
||||
m,v)},emscripten_glTexParameterf:(a,b,c)=>D.texParameterf(a,b,c),emscripten_glTexParameterfv:(a,b,c)=>{c=u()[c>>2];D.texParameterf(a,b,c)},emscripten_glTexParameteri:(a,b,c)=>D.texParameteri(a,b,c),emscripten_glTexParameteriv:(a,b,c)=>{c=r()[c>>2];D.texParameteri(a,b,c)},emscripten_glTexStorage2D:(a,b,c,e,f)=>D.texStorage2D(a,b,c,e,f),emscripten_glTexSubImage2D:(a,b,c,e,f,h,l,m,p)=>{if(2<=O.version){if(D.o){D.texSubImage2D(a,b,c,e,f,h,l,m,p);return}if(p){var v=vb(m);D.texSubImage2D(a,b,c,e,f,h,l,
|
||||
m,v,p>>>31-Math.clz32(v.BYTES_PER_ELEMENT));return}}p=p?wb(m,l,f,h,p):null;D.texSubImage2D(a,b,c,e,f,h,l,m,p)},emscripten_glUniform1f:(a,b)=>{D.uniform1f(P(a),b)},emscripten_glUniform1fv:(a,b,c)=>{if(2<=O.version)b&&D.uniform1fv(P(a),u(),c>>2,b);else{if(288>=b)for(var e=Q[b],f=0;f<b;++f)e[f]=u()[c+4*f>>2];else e=u().subarray(c>>2,c+4*b>>2);D.uniform1fv(P(a),e)}},emscripten_glUniform1i:(a,b)=>{D.uniform1i(P(a),b)},emscripten_glUniform1iv:(a,b,c)=>{if(2<=O.version)b&&D.uniform1iv(P(a),r(),c>>2,b);else{if(288>=
|
||||
b)for(var e=xb[b],f=0;f<b;++f)e[f]=r()[c+4*f>>2];else e=r().subarray(c>>2,c+4*b>>2);D.uniform1iv(P(a),e)}},emscripten_glUniform2f:(a,b,c)=>{D.uniform2f(P(a),b,c)},emscripten_glUniform2fv:(a,b,c)=>{if(2<=O.version)b&&D.uniform2fv(P(a),u(),c>>2,2*b);else{if(144>=b){b*=2;for(var e=Q[b],f=0;f<b;f+=2)e[f]=u()[c+4*f>>2],e[f+1]=u()[c+(4*f+4)>>2]}else e=u().subarray(c>>2,c+8*b>>2);D.uniform2fv(P(a),e)}},emscripten_glUniform2i:(a,b,c)=>{D.uniform2i(P(a),b,c)},emscripten_glUniform2iv:(a,b,c)=>{if(2<=O.version)b&&
|
||||
D.uniform2iv(P(a),r(),c>>2,2*b);else{if(144>=b){b*=2;for(var e=xb[b],f=0;f<b;f+=2)e[f]=r()[c+4*f>>2],e[f+1]=r()[c+(4*f+4)>>2]}else e=r().subarray(c>>2,c+8*b>>2);D.uniform2iv(P(a),e)}},emscripten_glUniform3f:(a,b,c,e)=>{D.uniform3f(P(a),b,c,e)},emscripten_glUniform3fv:(a,b,c)=>{if(2<=O.version)b&&D.uniform3fv(P(a),u(),c>>2,3*b);else{if(96>=b){b*=3;for(var e=Q[b],f=0;f<b;f+=3)e[f]=u()[c+4*f>>2],e[f+1]=u()[c+(4*f+4)>>2],e[f+2]=u()[c+(4*f+8)>>2]}else e=u().subarray(c>>2,c+12*b>>2);D.uniform3fv(P(a),e)}},
|
||||
emscripten_glUniform3i:(a,b,c,e)=>{D.uniform3i(P(a),b,c,e)},emscripten_glUniform3iv:(a,b,c)=>{if(2<=O.version)b&&D.uniform3iv(P(a),r(),c>>2,3*b);else{if(96>=b){b*=3;for(var e=xb[b],f=0;f<b;f+=3)e[f]=r()[c+4*f>>2],e[f+1]=r()[c+(4*f+4)>>2],e[f+2]=r()[c+(4*f+8)>>2]}else e=r().subarray(c>>2,c+12*b>>2);D.uniform3iv(P(a),e)}},emscripten_glUniform4f:(a,b,c,e,f)=>{D.uniform4f(P(a),b,c,e,f)},emscripten_glUniform4fv:(a,b,c)=>{if(2<=O.version)b&&D.uniform4fv(P(a),u(),c>>2,4*b);else{if(72>=b){var e=Q[4*b],f=
|
||||
u();c>>=2;b*=4;for(var h=0;h<b;h+=4){var l=c+h;e[h]=f[l];e[h+1]=f[l+1];e[h+2]=f[l+2];e[h+3]=f[l+3]}}else e=u().subarray(c>>2,c+16*b>>2);D.uniform4fv(P(a),e)}},emscripten_glUniform4i:(a,b,c,e,f)=>{D.uniform4i(P(a),b,c,e,f)},emscripten_glUniform4iv:(a,b,c)=>{if(2<=O.version)b&&D.uniform4iv(P(a),r(),c>>2,4*b);else{if(72>=b){b*=4;for(var e=xb[b],f=0;f<b;f+=4)e[f]=r()[c+4*f>>2],e[f+1]=r()[c+(4*f+4)>>2],e[f+2]=r()[c+(4*f+8)>>2],e[f+3]=r()[c+(4*f+12)>>2]}else e=r().subarray(c>>2,c+16*b>>2);D.uniform4iv(P(a),
|
||||
e)}},emscripten_glUniformMatrix2fv:(a,b,c,e)=>{if(2<=O.version)b&&D.uniformMatrix2fv(P(a),!!c,u(),e>>2,4*b);else{if(72>=b){b*=4;for(var f=Q[b],h=0;h<b;h+=4)f[h]=u()[e+4*h>>2],f[h+1]=u()[e+(4*h+4)>>2],f[h+2]=u()[e+(4*h+8)>>2],f[h+3]=u()[e+(4*h+12)>>2]}else f=u().subarray(e>>2,e+16*b>>2);D.uniformMatrix2fv(P(a),!!c,f)}},emscripten_glUniformMatrix3fv:(a,b,c,e)=>{if(2<=O.version)b&&D.uniformMatrix3fv(P(a),!!c,u(),e>>2,9*b);else{if(32>=b){b*=9;for(var f=Q[b],h=0;h<b;h+=9)f[h]=u()[e+4*h>>2],f[h+1]=u()[e+
|
||||
(4*h+4)>>2],f[h+2]=u()[e+(4*h+8)>>2],f[h+3]=u()[e+(4*h+12)>>2],f[h+4]=u()[e+(4*h+16)>>2],f[h+5]=u()[e+(4*h+20)>>2],f[h+6]=u()[e+(4*h+24)>>2],f[h+7]=u()[e+(4*h+28)>>2],f[h+8]=u()[e+(4*h+32)>>2]}else f=u().subarray(e>>2,e+36*b>>2);D.uniformMatrix3fv(P(a),!!c,f)}},emscripten_glUniformMatrix4fv:(a,b,c,e)=>{if(2<=O.version)b&&D.uniformMatrix4fv(P(a),!!c,u(),e>>2,16*b);else{if(18>=b){var f=Q[16*b],h=u();e>>=2;b*=16;for(var l=0;l<b;l+=16){var m=e+l;f[l]=h[m];f[l+1]=h[m+1];f[l+2]=h[m+2];f[l+3]=h[m+3];f[l+
|
||||
4]=h[m+4];f[l+5]=h[m+5];f[l+6]=h[m+6];f[l+7]=h[m+7];f[l+8]=h[m+8];f[l+9]=h[m+9];f[l+10]=h[m+10];f[l+11]=h[m+11];f[l+12]=h[m+12];f[l+13]=h[m+13];f[l+14]=h[m+14];f[l+15]=h[m+15]}}else f=u().subarray(e>>2,e+64*b>>2);D.uniformMatrix4fv(P(a),!!c,f)}},emscripten_glUseProgram:a=>{a=E[a];D.useProgram(a);D.N=a},emscripten_glVertexAttrib1f:(a,b)=>D.vertexAttrib1f(a,b),emscripten_glVertexAttrib2fv:(a,b)=>{D.vertexAttrib2f(a,u()[b>>2],u()[b+4>>2])},emscripten_glVertexAttrib3fv:(a,b)=>{D.vertexAttrib3f(a,u()[b>>
|
||||
2],u()[b+4>>2],u()[b+8>>2])},emscripten_glVertexAttrib4fv:(a,b)=>{D.vertexAttrib4f(a,u()[b>>2],u()[b+4>>2],u()[b+8>>2],u()[b+12>>2])},emscripten_glVertexAttribDivisor:(a,b)=>{D.vertexAttribDivisor(a,b)},emscripten_glVertexAttribIPointer:(a,b,c,e,f)=>{D.vertexAttribIPointer(a,b,c,e,f)},emscripten_glVertexAttribPointer:(a,b,c,e,f,h)=>{D.vertexAttribPointer(a,b,c,!!e,f,h)},emscripten_glViewport:(a,b,c,e)=>D.viewport(a,b,c,e),emscripten_glWaitSync:(a,b,c,e)=>{D.waitSync(K[a],b,(c>>>0)+4294967296*e)},
|
||||
emscripten_resize_heap:a=>{var b=q().length;a>>>=0;if(a<=b||2147483648<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+.2/c);e=Math.min(e,a+100663296);a:{e=(Math.min(2147483648,65536*Math.ceil(Math.max(a,e)/65536))-g.buffer.byteLength+65535)/65536|0;try{g.grow(e);n();var f=1;break a}catch(h){}f=void 0}if(f)return!0}return!1},emscripten_webgl_enable_extension:function(a,b){a=Za[a];b=Ka(b);b.startsWith("GL_")&&(b=b.substr(3));"ANGLE_instanced_arrays"==b&&Pa(D);"OES_vertex_array_object"==b&&Qa(D);"WEBGL_draw_buffers"==
|
||||
b&&Ra(D);"WEBGL_draw_instanced_base_vertex_base_instance"==b&&Sa(D);"WEBGL_multi_draw_instanced_base_vertex_base_instance"==b&&Ta(D);"WEBGL_multi_draw"==b&&(D.T=D.getExtension("WEBGL_multi_draw"));"EXT_polygon_offset_clamp"==b&&(D.P=D.getExtension("EXT_polygon_offset_clamp"));"EXT_clip_control"==b&&(D.O=D.getExtension("EXT_clip_control"));"WEBGL_polygon_mode"==b&&(D.Y=D.getExtension("WEBGL_polygon_mode"));return!!a.v.getExtension(b)},emscripten_webgl_get_current_context:()=>O?O.handle:0,emscripten_webgl_make_context_current:a=>
|
||||
{O=Za[a];w.$=D=O?.v;return!a||D?0:-5},environ_get:(a,b)=>{var c=0;Ab().forEach((e,f)=>{var h=b+c;f=t()[a+4*f>>2]=h;for(h=0;h<e.length;++h)d()[f++]=e.charCodeAt(h);d()[f]=0;c+=e.length+1});return 0},environ_sizes_get:(a,b)=>{var c=Ab();t()[a>>2]=c.length;var e=0;c.forEach(f=>e+=f.length+1);t()[b>>2]=e;return 0},fd_close:()=>52,fd_pread:function(){return 52},fd_read:()=>52,fd_seek:function(){return 70},fd_write:(a,b,c,e)=>{for(var f=0,h=0;h<c;h++){var l=t()[b>>2],m=t()[b+4>>2];b+=8;for(var p=0;p<m;p++){var v=
|
||||
q()[l+p],T=Bb[a];0===v||10===v?((1===a?na:y)(Ja(T)),T.length=0):T.push(v)}f+=m}t()[e>>2]=f;return 0},glDeleteTextures:hb,glGetIntegerv:ob,glGetString:sb,glGetStringi:tb,invoke_ii:bc,invoke_iii:cc,invoke_iiii:dc,invoke_iiiii:ec,invoke_iiiiiii:fc,invoke_vi:gc,invoke_vii:hc,invoke_viii:ic,invoke_viiii:jc,invoke_viiiiiii:kc,proc_exit:Na,skwasm_captureImageBitmap:Eb,skwasm_connectThread:Fb,skwasm_createGlTextureFromTextureSource:Gb,skwasm_createOffscreenCanvas:Hb,skwasm_dispatchDisposeSurface:Ib,skwasm_dispatchRasterizeImage:Jb,
|
||||
skwasm_dispatchRenderPictures:Kb,skwasm_disposeAssociatedObjectOnThread:Lb,skwasm_getAssociatedObject:Mb,skwasm_postRasterizeResult:Nb,skwasm_resizeCanvas:Ob,skwasm_resolveAndPostImages:Pb,skwasm_setAssociatedObjectOnThread:Qb},W=function(){function a(c){W=c.exports;w.wasmExports=W;g=W.memory;w.wasmMemory=g;n();S=W.__indirect_function_table;ta.unshift(W.__wasm_call_ctors);z--;0==z&&(null!==va&&(clearInterval(va),va=null),A&&(c=A,A=null,c()));return W}var b={env:lc,wasi_snapshot_preview1:lc};z++;if(w.instantiateWasm)try{return w.instantiateWasm(b,
|
||||
a)}catch(c){y(`Module.instantiateWasm callback failed with error: ${c}`),fa(c)}ya??=xa("skwasm_st.wasm")?"skwasm_st.wasm":x+"skwasm_st.wasm";Ba(b,function(c){a(c.instance,c.module)}).catch(fa);return{}}();w._canvas_saveLayer=(a,b,c,e,f)=>(w._canvas_saveLayer=W.canvas_saveLayer)(a,b,c,e,f);w._canvas_save=a=>(w._canvas_save=W.canvas_save)(a);w._canvas_restore=a=>(w._canvas_restore=W.canvas_restore)(a);w._canvas_restoreToCount=(a,b)=>(w._canvas_restoreToCount=W.canvas_restoreToCount)(a,b);
|
||||
w._canvas_getSaveCount=a=>(w._canvas_getSaveCount=W.canvas_getSaveCount)(a);w._canvas_translate=(a,b,c)=>(w._canvas_translate=W.canvas_translate)(a,b,c);w._canvas_scale=(a,b,c)=>(w._canvas_scale=W.canvas_scale)(a,b,c);w._canvas_rotate=(a,b)=>(w._canvas_rotate=W.canvas_rotate)(a,b);w._canvas_skew=(a,b,c)=>(w._canvas_skew=W.canvas_skew)(a,b,c);w._canvas_transform=(a,b)=>(w._canvas_transform=W.canvas_transform)(a,b);w._canvas_clipRect=(a,b,c,e)=>(w._canvas_clipRect=W.canvas_clipRect)(a,b,c,e);
|
||||
w._canvas_clipRRect=(a,b,c)=>(w._canvas_clipRRect=W.canvas_clipRRect)(a,b,c);w._canvas_clipPath=(a,b,c)=>(w._canvas_clipPath=W.canvas_clipPath)(a,b,c);w._canvas_drawColor=(a,b,c)=>(w._canvas_drawColor=W.canvas_drawColor)(a,b,c);w._canvas_drawLine=(a,b,c,e,f,h)=>(w._canvas_drawLine=W.canvas_drawLine)(a,b,c,e,f,h);w._canvas_drawPaint=(a,b)=>(w._canvas_drawPaint=W.canvas_drawPaint)(a,b);w._canvas_drawRect=(a,b,c)=>(w._canvas_drawRect=W.canvas_drawRect)(a,b,c);
|
||||
w._canvas_drawRRect=(a,b,c)=>(w._canvas_drawRRect=W.canvas_drawRRect)(a,b,c);w._canvas_drawDRRect=(a,b,c,e)=>(w._canvas_drawDRRect=W.canvas_drawDRRect)(a,b,c,e);w._canvas_drawOval=(a,b,c)=>(w._canvas_drawOval=W.canvas_drawOval)(a,b,c);w._canvas_drawCircle=(a,b,c,e,f)=>(w._canvas_drawCircle=W.canvas_drawCircle)(a,b,c,e,f);w._canvas_drawArc=(a,b,c,e,f,h)=>(w._canvas_drawArc=W.canvas_drawArc)(a,b,c,e,f,h);w._canvas_drawPath=(a,b,c)=>(w._canvas_drawPath=W.canvas_drawPath)(a,b,c);
|
||||
w._canvas_drawShadow=(a,b,c,e,f,h)=>(w._canvas_drawShadow=W.canvas_drawShadow)(a,b,c,e,f,h);w._canvas_drawParagraph=(a,b,c,e)=>(w._canvas_drawParagraph=W.canvas_drawParagraph)(a,b,c,e);w._canvas_drawPicture=(a,b)=>(w._canvas_drawPicture=W.canvas_drawPicture)(a,b);w._canvas_drawImage=(a,b,c,e,f,h)=>(w._canvas_drawImage=W.canvas_drawImage)(a,b,c,e,f,h);w._canvas_drawImageRect=(a,b,c,e,f,h)=>(w._canvas_drawImageRect=W.canvas_drawImageRect)(a,b,c,e,f,h);
|
||||
w._canvas_drawImageNine=(a,b,c,e,f,h)=>(w._canvas_drawImageNine=W.canvas_drawImageNine)(a,b,c,e,f,h);w._canvas_drawVertices=(a,b,c,e)=>(w._canvas_drawVertices=W.canvas_drawVertices)(a,b,c,e);w._canvas_drawPoints=(a,b,c,e,f)=>(w._canvas_drawPoints=W.canvas_drawPoints)(a,b,c,e,f);w._canvas_drawAtlas=(a,b,c,e,f,h,l,m,p)=>(w._canvas_drawAtlas=W.canvas_drawAtlas)(a,b,c,e,f,h,l,m,p);w._canvas_getTransform=(a,b)=>(w._canvas_getTransform=W.canvas_getTransform)(a,b);
|
||||
w._canvas_getLocalClipBounds=(a,b)=>(w._canvas_getLocalClipBounds=W.canvas_getLocalClipBounds)(a,b);w._canvas_getDeviceClipBounds=(a,b)=>(w._canvas_getDeviceClipBounds=W.canvas_getDeviceClipBounds)(a,b);w._contourMeasureIter_create=(a,b,c)=>(w._contourMeasureIter_create=W.contourMeasureIter_create)(a,b,c);w._contourMeasureIter_next=a=>(w._contourMeasureIter_next=W.contourMeasureIter_next)(a);w._contourMeasureIter_dispose=a=>(w._contourMeasureIter_dispose=W.contourMeasureIter_dispose)(a);
|
||||
w._contourMeasure_dispose=a=>(w._contourMeasure_dispose=W.contourMeasure_dispose)(a);w._contourMeasure_length=a=>(w._contourMeasure_length=W.contourMeasure_length)(a);w._contourMeasure_isClosed=a=>(w._contourMeasure_isClosed=W.contourMeasure_isClosed)(a);w._contourMeasure_getPosTan=(a,b,c,e)=>(w._contourMeasure_getPosTan=W.contourMeasure_getPosTan)(a,b,c,e);w._contourMeasure_getSegment=(a,b,c,e)=>(w._contourMeasure_getSegment=W.contourMeasure_getSegment)(a,b,c,e);
|
||||
w._skData_create=a=>(w._skData_create=W.skData_create)(a);w._skData_getPointer=a=>(w._skData_getPointer=W.skData_getPointer)(a);w._skData_getConstPointer=a=>(w._skData_getConstPointer=W.skData_getConstPointer)(a);w._skData_getSize=a=>(w._skData_getSize=W.skData_getSize)(a);w._skData_dispose=a=>(w._skData_dispose=W.skData_dispose)(a);w._imageFilter_createBlur=(a,b,c)=>(w._imageFilter_createBlur=W.imageFilter_createBlur)(a,b,c);
|
||||
w._imageFilter_createDilate=(a,b)=>(w._imageFilter_createDilate=W.imageFilter_createDilate)(a,b);w._imageFilter_createErode=(a,b)=>(w._imageFilter_createErode=W.imageFilter_createErode)(a,b);w._imageFilter_createMatrix=(a,b)=>(w._imageFilter_createMatrix=W.imageFilter_createMatrix)(a,b);w._imageFilter_createFromColorFilter=a=>(w._imageFilter_createFromColorFilter=W.imageFilter_createFromColorFilter)(a);w._imageFilter_compose=(a,b)=>(w._imageFilter_compose=W.imageFilter_compose)(a,b);
|
||||
w._imageFilter_dispose=a=>(w._imageFilter_dispose=W.imageFilter_dispose)(a);w._imageFilter_getFilterBounds=(a,b)=>(w._imageFilter_getFilterBounds=W.imageFilter_getFilterBounds)(a,b);w._colorFilter_createMode=(a,b)=>(w._colorFilter_createMode=W.colorFilter_createMode)(a,b);w._colorFilter_createMatrix=a=>(w._colorFilter_createMatrix=W.colorFilter_createMatrix)(a);w._colorFilter_createSRGBToLinearGamma=()=>(w._colorFilter_createSRGBToLinearGamma=W.colorFilter_createSRGBToLinearGamma)();
|
||||
w._colorFilter_createLinearToSRGBGamma=()=>(w._colorFilter_createLinearToSRGBGamma=W.colorFilter_createLinearToSRGBGamma)();w._colorFilter_compose=(a,b)=>(w._colorFilter_compose=W.colorFilter_compose)(a,b);w._colorFilter_dispose=a=>(w._colorFilter_dispose=W.colorFilter_dispose)(a);w._maskFilter_createBlur=(a,b)=>(w._maskFilter_createBlur=W.maskFilter_createBlur)(a,b);w._maskFilter_dispose=a=>(w._maskFilter_dispose=W.maskFilter_dispose)(a);w._fontCollection_create=()=>(w._fontCollection_create=W.fontCollection_create)();
|
||||
w._fontCollection_dispose=a=>(w._fontCollection_dispose=W.fontCollection_dispose)(a);w._typeface_create=a=>(w._typeface_create=W.typeface_create)(a);w._typeface_dispose=a=>(w._typeface_dispose=W.typeface_dispose)(a);w._typefaces_filterCoveredCodePoints=(a,b,c,e)=>(w._typefaces_filterCoveredCodePoints=W.typefaces_filterCoveredCodePoints)(a,b,c,e);w._fontCollection_registerTypeface=(a,b,c)=>(w._fontCollection_registerTypeface=W.fontCollection_registerTypeface)(a,b,c);
|
||||
w._fontCollection_clearCaches=a=>(w._fontCollection_clearCaches=W.fontCollection_clearCaches)(a);w._image_createFromPicture=(a,b,c)=>(w._image_createFromPicture=W.image_createFromPicture)(a,b,c);w._image_createFromPixels=(a,b,c,e,f)=>(w._image_createFromPixels=W.image_createFromPixels)(a,b,c,e,f);w._image_createFromTextureSource=(a,b,c,e)=>(w._image_createFromTextureSource=W.image_createFromTextureSource)(a,b,c,e);w._image_ref=a=>(w._image_ref=W.image_ref)(a);
|
||||
w._image_dispose=a=>(w._image_dispose=W.image_dispose)(a);w._image_getWidth=a=>(w._image_getWidth=W.image_getWidth)(a);w._image_getHeight=a=>(w._image_getHeight=W.image_getHeight)(a);w._paint_create=(a,b,c,e,f,h,l,m)=>(w._paint_create=W.paint_create)(a,b,c,e,f,h,l,m);w._paint_dispose=a=>(w._paint_dispose=W.paint_dispose)(a);w._paint_setShader=(a,b)=>(w._paint_setShader=W.paint_setShader)(a,b);w._paint_setImageFilter=(a,b)=>(w._paint_setImageFilter=W.paint_setImageFilter)(a,b);
|
||||
w._paint_setColorFilter=(a,b)=>(w._paint_setColorFilter=W.paint_setColorFilter)(a,b);w._paint_setMaskFilter=(a,b)=>(w._paint_setMaskFilter=W.paint_setMaskFilter)(a,b);w._path_create=()=>(w._path_create=W.path_create)();w._path_dispose=a=>(w._path_dispose=W.path_dispose)(a);w._path_copy=a=>(w._path_copy=W.path_copy)(a);w._path_setFillType=(a,b)=>(w._path_setFillType=W.path_setFillType)(a,b);w._path_getFillType=a=>(w._path_getFillType=W.path_getFillType)(a);
|
||||
w._path_moveTo=(a,b,c)=>(w._path_moveTo=W.path_moveTo)(a,b,c);w._path_relativeMoveTo=(a,b,c)=>(w._path_relativeMoveTo=W.path_relativeMoveTo)(a,b,c);w._path_lineTo=(a,b,c)=>(w._path_lineTo=W.path_lineTo)(a,b,c);w._path_relativeLineTo=(a,b,c)=>(w._path_relativeLineTo=W.path_relativeLineTo)(a,b,c);w._path_quadraticBezierTo=(a,b,c,e,f)=>(w._path_quadraticBezierTo=W.path_quadraticBezierTo)(a,b,c,e,f);
|
||||
w._path_relativeQuadraticBezierTo=(a,b,c,e,f)=>(w._path_relativeQuadraticBezierTo=W.path_relativeQuadraticBezierTo)(a,b,c,e,f);w._path_cubicTo=(a,b,c,e,f,h,l)=>(w._path_cubicTo=W.path_cubicTo)(a,b,c,e,f,h,l);w._path_relativeCubicTo=(a,b,c,e,f,h,l)=>(w._path_relativeCubicTo=W.path_relativeCubicTo)(a,b,c,e,f,h,l);w._path_conicTo=(a,b,c,e,f,h)=>(w._path_conicTo=W.path_conicTo)(a,b,c,e,f,h);w._path_relativeConicTo=(a,b,c,e,f,h)=>(w._path_relativeConicTo=W.path_relativeConicTo)(a,b,c,e,f,h);
|
||||
w._path_arcToOval=(a,b,c,e,f)=>(w._path_arcToOval=W.path_arcToOval)(a,b,c,e,f);w._path_arcToRotated=(a,b,c,e,f,h,l,m)=>(w._path_arcToRotated=W.path_arcToRotated)(a,b,c,e,f,h,l,m);w._path_relativeArcToRotated=(a,b,c,e,f,h,l,m)=>(w._path_relativeArcToRotated=W.path_relativeArcToRotated)(a,b,c,e,f,h,l,m);w._path_addRect=(a,b)=>(w._path_addRect=W.path_addRect)(a,b);w._path_addOval=(a,b)=>(w._path_addOval=W.path_addOval)(a,b);w._path_addArc=(a,b,c,e)=>(w._path_addArc=W.path_addArc)(a,b,c,e);
|
||||
w._path_addPolygon=(a,b,c,e)=>(w._path_addPolygon=W.path_addPolygon)(a,b,c,e);w._path_addRRect=(a,b)=>(w._path_addRRect=W.path_addRRect)(a,b);w._path_addPath=(a,b,c,e)=>(w._path_addPath=W.path_addPath)(a,b,c,e);w._path_close=a=>(w._path_close=W.path_close)(a);w._path_reset=a=>(w._path_reset=W.path_reset)(a);w._path_contains=(a,b,c)=>(w._path_contains=W.path_contains)(a,b,c);w._path_transform=(a,b)=>(w._path_transform=W.path_transform)(a,b);
|
||||
w._path_getBounds=(a,b)=>(w._path_getBounds=W.path_getBounds)(a,b);w._path_combine=(a,b,c)=>(w._path_combine=W.path_combine)(a,b,c);w._path_getSvgString=a=>(w._path_getSvgString=W.path_getSvgString)(a);w._pictureRecorder_create=()=>(w._pictureRecorder_create=W.pictureRecorder_create)();w._pictureRecorder_dispose=a=>(w._pictureRecorder_dispose=W.pictureRecorder_dispose)(a);w._pictureRecorder_beginRecording=(a,b)=>(w._pictureRecorder_beginRecording=W.pictureRecorder_beginRecording)(a,b);
|
||||
w._pictureRecorder_endRecording=a=>(w._pictureRecorder_endRecording=W.pictureRecorder_endRecording)(a);w._picture_getCullRect=(a,b)=>(w._picture_getCullRect=W.picture_getCullRect)(a,b);w._picture_dispose=a=>(w._picture_dispose=W.picture_dispose)(a);w._picture_approximateBytesUsed=a=>(w._picture_approximateBytesUsed=W.picture_approximateBytesUsed)(a);w._shader_createLinearGradient=(a,b,c,e,f,h)=>(w._shader_createLinearGradient=W.shader_createLinearGradient)(a,b,c,e,f,h);
|
||||
w._shader_createRadialGradient=(a,b,c,e,f,h,l,m)=>(w._shader_createRadialGradient=W.shader_createRadialGradient)(a,b,c,e,f,h,l,m);w._shader_createConicalGradient=(a,b,c,e,f,h,l,m)=>(w._shader_createConicalGradient=W.shader_createConicalGradient)(a,b,c,e,f,h,l,m);w._shader_createSweepGradient=(a,b,c,e,f,h,l,m,p)=>(w._shader_createSweepGradient=W.shader_createSweepGradient)(a,b,c,e,f,h,l,m,p);w._shader_dispose=a=>(w._shader_dispose=W.shader_dispose)(a);
|
||||
w._runtimeEffect_create=a=>(w._runtimeEffect_create=W.runtimeEffect_create)(a);w._runtimeEffect_dispose=a=>(w._runtimeEffect_dispose=W.runtimeEffect_dispose)(a);w._runtimeEffect_getUniformSize=a=>(w._runtimeEffect_getUniformSize=W.runtimeEffect_getUniformSize)(a);w._shader_createRuntimeEffectShader=(a,b,c,e)=>(w._shader_createRuntimeEffectShader=W.shader_createRuntimeEffectShader)(a,b,c,e);w._shader_createFromImage=(a,b,c,e,f)=>(w._shader_createFromImage=W.shader_createFromImage)(a,b,c,e,f);
|
||||
w._skString_allocate=a=>(w._skString_allocate=W.skString_allocate)(a);w._skString_getData=a=>(w._skString_getData=W.skString_getData)(a);w._skString_getLength=a=>(w._skString_getLength=W.skString_getLength)(a);w._skString_free=a=>(w._skString_free=W.skString_free)(a);w._skString16_allocate=a=>(w._skString16_allocate=W.skString16_allocate)(a);w._skString16_getData=a=>(w._skString16_getData=W.skString16_getData)(a);w._skString16_free=a=>(w._skString16_free=W.skString16_free)(a);
|
||||
w._surface_create=()=>(w._surface_create=W.surface_create)();w._surface_getThreadId=a=>(w._surface_getThreadId=W.surface_getThreadId)(a);w._surface_setCallbackHandler=(a,b)=>(w._surface_setCallbackHandler=W.surface_setCallbackHandler)(a,b);w._surface_destroy=a=>(w._surface_destroy=W.surface_destroy)(a);var Yb=w._surface_dispose=a=>(Yb=w._surface_dispose=W.surface_dispose)(a);w._surface_renderPictures=(a,b,c)=>(w._surface_renderPictures=W.surface_renderPictures)(a,b,c);
|
||||
var Wb=w._surface_renderPicturesOnWorker=(a,b,c,e,f)=>(Wb=w._surface_renderPicturesOnWorker=W.surface_renderPicturesOnWorker)(a,b,c,e,f);w._surface_rasterizeImage=(a,b,c)=>(w._surface_rasterizeImage=W.surface_rasterizeImage)(a,b,c);
|
||||
var Zb=w._surface_rasterizeImageOnWorker=(a,b,c,e)=>(Zb=w._surface_rasterizeImageOnWorker=W.surface_rasterizeImageOnWorker)(a,b,c,e),Xb=w._surface_onRenderComplete=(a,b,c)=>(Xb=w._surface_onRenderComplete=W.surface_onRenderComplete)(a,b,c),$b=w._surface_onRasterizeComplete=(a,b,c)=>($b=w._surface_onRasterizeComplete=W.surface_onRasterizeComplete)(a,b,c);w._lineMetrics_create=(a,b,c,e,f,h,l,m,p)=>(w._lineMetrics_create=W.lineMetrics_create)(a,b,c,e,f,h,l,m,p);
|
||||
w._lineMetrics_dispose=a=>(w._lineMetrics_dispose=W.lineMetrics_dispose)(a);w._lineMetrics_getHardBreak=a=>(w._lineMetrics_getHardBreak=W.lineMetrics_getHardBreak)(a);w._lineMetrics_getAscent=a=>(w._lineMetrics_getAscent=W.lineMetrics_getAscent)(a);w._lineMetrics_getDescent=a=>(w._lineMetrics_getDescent=W.lineMetrics_getDescent)(a);w._lineMetrics_getUnscaledAscent=a=>(w._lineMetrics_getUnscaledAscent=W.lineMetrics_getUnscaledAscent)(a);w._lineMetrics_getHeight=a=>(w._lineMetrics_getHeight=W.lineMetrics_getHeight)(a);
|
||||
w._lineMetrics_getWidth=a=>(w._lineMetrics_getWidth=W.lineMetrics_getWidth)(a);w._lineMetrics_getLeft=a=>(w._lineMetrics_getLeft=W.lineMetrics_getLeft)(a);w._lineMetrics_getBaseline=a=>(w._lineMetrics_getBaseline=W.lineMetrics_getBaseline)(a);w._lineMetrics_getLineNumber=a=>(w._lineMetrics_getLineNumber=W.lineMetrics_getLineNumber)(a);w._lineMetrics_getStartIndex=a=>(w._lineMetrics_getStartIndex=W.lineMetrics_getStartIndex)(a);w._lineMetrics_getEndIndex=a=>(w._lineMetrics_getEndIndex=W.lineMetrics_getEndIndex)(a);
|
||||
w._paragraph_dispose=a=>(w._paragraph_dispose=W.paragraph_dispose)(a);w._paragraph_getWidth=a=>(w._paragraph_getWidth=W.paragraph_getWidth)(a);w._paragraph_getHeight=a=>(w._paragraph_getHeight=W.paragraph_getHeight)(a);w._paragraph_getLongestLine=a=>(w._paragraph_getLongestLine=W.paragraph_getLongestLine)(a);w._paragraph_getMinIntrinsicWidth=a=>(w._paragraph_getMinIntrinsicWidth=W.paragraph_getMinIntrinsicWidth)(a);w._paragraph_getMaxIntrinsicWidth=a=>(w._paragraph_getMaxIntrinsicWidth=W.paragraph_getMaxIntrinsicWidth)(a);
|
||||
w._paragraph_getAlphabeticBaseline=a=>(w._paragraph_getAlphabeticBaseline=W.paragraph_getAlphabeticBaseline)(a);w._paragraph_getIdeographicBaseline=a=>(w._paragraph_getIdeographicBaseline=W.paragraph_getIdeographicBaseline)(a);w._paragraph_getDidExceedMaxLines=a=>(w._paragraph_getDidExceedMaxLines=W.paragraph_getDidExceedMaxLines)(a);w._paragraph_layout=(a,b)=>(w._paragraph_layout=W.paragraph_layout)(a,b);
|
||||
w._paragraph_getPositionForOffset=(a,b,c,e)=>(w._paragraph_getPositionForOffset=W.paragraph_getPositionForOffset)(a,b,c,e);w._paragraph_getClosestGlyphInfoAtCoordinate=(a,b,c,e,f,h)=>(w._paragraph_getClosestGlyphInfoAtCoordinate=W.paragraph_getClosestGlyphInfoAtCoordinate)(a,b,c,e,f,h);w._paragraph_getGlyphInfoAt=(a,b,c,e,f)=>(w._paragraph_getGlyphInfoAt=W.paragraph_getGlyphInfoAt)(a,b,c,e,f);w._paragraph_getWordBoundary=(a,b,c)=>(w._paragraph_getWordBoundary=W.paragraph_getWordBoundary)(a,b,c);
|
||||
w._paragraph_getLineCount=a=>(w._paragraph_getLineCount=W.paragraph_getLineCount)(a);w._paragraph_getLineNumberAt=(a,b)=>(w._paragraph_getLineNumberAt=W.paragraph_getLineNumberAt)(a,b);w._paragraph_getLineMetricsAtIndex=(a,b)=>(w._paragraph_getLineMetricsAtIndex=W.paragraph_getLineMetricsAtIndex)(a,b);w._textBoxList_dispose=a=>(w._textBoxList_dispose=W.textBoxList_dispose)(a);w._textBoxList_getLength=a=>(w._textBoxList_getLength=W.textBoxList_getLength)(a);
|
||||
w._textBoxList_getBoxAtIndex=(a,b,c)=>(w._textBoxList_getBoxAtIndex=W.textBoxList_getBoxAtIndex)(a,b,c);w._paragraph_getBoxesForRange=(a,b,c,e,f)=>(w._paragraph_getBoxesForRange=W.paragraph_getBoxesForRange)(a,b,c,e,f);w._paragraph_getBoxesForPlaceholders=a=>(w._paragraph_getBoxesForPlaceholders=W.paragraph_getBoxesForPlaceholders)(a);w._paragraph_getUnresolvedCodePoints=(a,b,c)=>(w._paragraph_getUnresolvedCodePoints=W.paragraph_getUnresolvedCodePoints)(a,b,c);
|
||||
w._paragraphBuilder_create=(a,b)=>(w._paragraphBuilder_create=W.paragraphBuilder_create)(a,b);w._paragraphBuilder_dispose=a=>(w._paragraphBuilder_dispose=W.paragraphBuilder_dispose)(a);w._paragraphBuilder_addPlaceholder=(a,b,c,e,f,h)=>(w._paragraphBuilder_addPlaceholder=W.paragraphBuilder_addPlaceholder)(a,b,c,e,f,h);w._paragraphBuilder_addText=(a,b)=>(w._paragraphBuilder_addText=W.paragraphBuilder_addText)(a,b);
|
||||
w._paragraphBuilder_getUtf8Text=(a,b)=>(w._paragraphBuilder_getUtf8Text=W.paragraphBuilder_getUtf8Text)(a,b);w._paragraphBuilder_pushStyle=(a,b)=>(w._paragraphBuilder_pushStyle=W.paragraphBuilder_pushStyle)(a,b);w._paragraphBuilder_pop=a=>(w._paragraphBuilder_pop=W.paragraphBuilder_pop)(a);w._paragraphBuilder_build=a=>(w._paragraphBuilder_build=W.paragraphBuilder_build)(a);w._unicodePositionBuffer_create=a=>(w._unicodePositionBuffer_create=W.unicodePositionBuffer_create)(a);
|
||||
w._unicodePositionBuffer_getDataPointer=a=>(w._unicodePositionBuffer_getDataPointer=W.unicodePositionBuffer_getDataPointer)(a);w._unicodePositionBuffer_free=a=>(w._unicodePositionBuffer_free=W.unicodePositionBuffer_free)(a);w._lineBreakBuffer_create=a=>(w._lineBreakBuffer_create=W.lineBreakBuffer_create)(a);w._lineBreakBuffer_getDataPointer=a=>(w._lineBreakBuffer_getDataPointer=W.lineBreakBuffer_getDataPointer)(a);w._lineBreakBuffer_free=a=>(w._lineBreakBuffer_free=W.lineBreakBuffer_free)(a);
|
||||
w._paragraphBuilder_setGraphemeBreaksUtf16=(a,b)=>(w._paragraphBuilder_setGraphemeBreaksUtf16=W.paragraphBuilder_setGraphemeBreaksUtf16)(a,b);w._paragraphBuilder_setWordBreaksUtf16=(a,b)=>(w._paragraphBuilder_setWordBreaksUtf16=W.paragraphBuilder_setWordBreaksUtf16)(a,b);w._paragraphBuilder_setLineBreaksUtf16=(a,b)=>(w._paragraphBuilder_setLineBreaksUtf16=W.paragraphBuilder_setLineBreaksUtf16)(a,b);w._paragraphStyle_create=()=>(w._paragraphStyle_create=W.paragraphStyle_create)();
|
||||
w._paragraphStyle_dispose=a=>(w._paragraphStyle_dispose=W.paragraphStyle_dispose)(a);w._paragraphStyle_setTextAlign=(a,b)=>(w._paragraphStyle_setTextAlign=W.paragraphStyle_setTextAlign)(a,b);w._paragraphStyle_setTextDirection=(a,b)=>(w._paragraphStyle_setTextDirection=W.paragraphStyle_setTextDirection)(a,b);w._paragraphStyle_setMaxLines=(a,b)=>(w._paragraphStyle_setMaxLines=W.paragraphStyle_setMaxLines)(a,b);
|
||||
w._paragraphStyle_setHeight=(a,b)=>(w._paragraphStyle_setHeight=W.paragraphStyle_setHeight)(a,b);w._paragraphStyle_setTextHeightBehavior=(a,b,c)=>(w._paragraphStyle_setTextHeightBehavior=W.paragraphStyle_setTextHeightBehavior)(a,b,c);w._paragraphStyle_setEllipsis=(a,b)=>(w._paragraphStyle_setEllipsis=W.paragraphStyle_setEllipsis)(a,b);w._paragraphStyle_setStrutStyle=(a,b)=>(w._paragraphStyle_setStrutStyle=W.paragraphStyle_setStrutStyle)(a,b);
|
||||
w._paragraphStyle_setTextStyle=(a,b)=>(w._paragraphStyle_setTextStyle=W.paragraphStyle_setTextStyle)(a,b);w._paragraphStyle_setApplyRoundingHack=(a,b)=>(w._paragraphStyle_setApplyRoundingHack=W.paragraphStyle_setApplyRoundingHack)(a,b);w._strutStyle_create=()=>(w._strutStyle_create=W.strutStyle_create)();w._strutStyle_dispose=a=>(w._strutStyle_dispose=W.strutStyle_dispose)(a);w._strutStyle_setFontFamilies=(a,b,c)=>(w._strutStyle_setFontFamilies=W.strutStyle_setFontFamilies)(a,b,c);
|
||||
w._strutStyle_setFontSize=(a,b)=>(w._strutStyle_setFontSize=W.strutStyle_setFontSize)(a,b);w._strutStyle_setHeight=(a,b)=>(w._strutStyle_setHeight=W.strutStyle_setHeight)(a,b);w._strutStyle_setHalfLeading=(a,b)=>(w._strutStyle_setHalfLeading=W.strutStyle_setHalfLeading)(a,b);w._strutStyle_setLeading=(a,b)=>(w._strutStyle_setLeading=W.strutStyle_setLeading)(a,b);w._strutStyle_setFontStyle=(a,b,c)=>(w._strutStyle_setFontStyle=W.strutStyle_setFontStyle)(a,b,c);
|
||||
w._strutStyle_setForceStrutHeight=(a,b)=>(w._strutStyle_setForceStrutHeight=W.strutStyle_setForceStrutHeight)(a,b);w._textStyle_create=()=>(w._textStyle_create=W.textStyle_create)();w._textStyle_copy=a=>(w._textStyle_copy=W.textStyle_copy)(a);w._textStyle_dispose=a=>(w._textStyle_dispose=W.textStyle_dispose)(a);w._textStyle_setColor=(a,b)=>(w._textStyle_setColor=W.textStyle_setColor)(a,b);w._textStyle_setDecoration=(a,b)=>(w._textStyle_setDecoration=W.textStyle_setDecoration)(a,b);
|
||||
w._textStyle_setDecorationColor=(a,b)=>(w._textStyle_setDecorationColor=W.textStyle_setDecorationColor)(a,b);w._textStyle_setDecorationStyle=(a,b)=>(w._textStyle_setDecorationStyle=W.textStyle_setDecorationStyle)(a,b);w._textStyle_setDecorationThickness=(a,b)=>(w._textStyle_setDecorationThickness=W.textStyle_setDecorationThickness)(a,b);w._textStyle_setFontStyle=(a,b,c)=>(w._textStyle_setFontStyle=W.textStyle_setFontStyle)(a,b,c);
|
||||
w._textStyle_setTextBaseline=(a,b)=>(w._textStyle_setTextBaseline=W.textStyle_setTextBaseline)(a,b);w._textStyle_clearFontFamilies=a=>(w._textStyle_clearFontFamilies=W.textStyle_clearFontFamilies)(a);w._textStyle_addFontFamilies=(a,b,c)=>(w._textStyle_addFontFamilies=W.textStyle_addFontFamilies)(a,b,c);w._textStyle_setFontSize=(a,b)=>(w._textStyle_setFontSize=W.textStyle_setFontSize)(a,b);w._textStyle_setLetterSpacing=(a,b)=>(w._textStyle_setLetterSpacing=W.textStyle_setLetterSpacing)(a,b);
|
||||
w._textStyle_setWordSpacing=(a,b)=>(w._textStyle_setWordSpacing=W.textStyle_setWordSpacing)(a,b);w._textStyle_setHeight=(a,b)=>(w._textStyle_setHeight=W.textStyle_setHeight)(a,b);w._textStyle_setHalfLeading=(a,b)=>(w._textStyle_setHalfLeading=W.textStyle_setHalfLeading)(a,b);w._textStyle_setLocale=(a,b)=>(w._textStyle_setLocale=W.textStyle_setLocale)(a,b);w._textStyle_setBackground=(a,b)=>(w._textStyle_setBackground=W.textStyle_setBackground)(a,b);
|
||||
w._textStyle_setForeground=(a,b)=>(w._textStyle_setForeground=W.textStyle_setForeground)(a,b);w._textStyle_addShadow=(a,b,c,e,f)=>(w._textStyle_addShadow=W.textStyle_addShadow)(a,b,c,e,f);w._textStyle_addFontFeature=(a,b,c)=>(w._textStyle_addFontFeature=W.textStyle_addFontFeature)(a,b,c);w._textStyle_setFontVariations=(a,b,c,e)=>(w._textStyle_setFontVariations=W.textStyle_setFontVariations)(a,b,c,e);w._vertices_create=(a,b,c,e,f,h,l)=>(w._vertices_create=W.vertices_create)(a,b,c,e,f,h,l);
|
||||
w._vertices_dispose=a=>(w._vertices_dispose=W.vertices_dispose)(a);w._skwasm_isMultiThreaded=()=>(w._skwasm_isMultiThreaded=W.skwasm_isMultiThreaded)();var qb=a=>(qb=W.malloc)(a),ac=(a,b)=>(ac=W._emscripten_timeout)(a,b),X=(a,b)=>(X=W.setThrew)(a,b),Y=a=>(Y=W._emscripten_stack_restore)(a),Sb=a=>(Sb=W._emscripten_stack_alloc)(a),Z=()=>(Z=W.emscripten_stack_get_current)();function cc(a,b,c){var e=Z();try{return S.get(a)(b,c)}catch(f){Y(e);if(f!==f+0)throw f;X(1,0)}}
|
||||
function hc(a,b,c){var e=Z();try{S.get(a)(b,c)}catch(f){Y(e);if(f!==f+0)throw f;X(1,0)}}function bc(a,b){var c=Z();try{return S.get(a)(b)}catch(e){Y(c);if(e!==e+0)throw e;X(1,0)}}function ic(a,b,c,e){var f=Z();try{S.get(a)(b,c,e)}catch(h){Y(f);if(h!==h+0)throw h;X(1,0)}}function dc(a,b,c,e){var f=Z();try{return S.get(a)(b,c,e)}catch(h){Y(f);if(h!==h+0)throw h;X(1,0)}}function jc(a,b,c,e,f){var h=Z();try{S.get(a)(b,c,e,f)}catch(l){Y(h);if(l!==l+0)throw l;X(1,0)}}
|
||||
function kc(a,b,c,e,f,h,l,m){var p=Z();try{S.get(a)(b,c,e,f,h,l,m)}catch(v){Y(p);if(v!==v+0)throw v;X(1,0)}}function gc(a,b){var c=Z();try{S.get(a)(b)}catch(e){Y(c);if(e!==e+0)throw e;X(1,0)}}function fc(a,b,c,e,f,h,l){var m=Z();try{return S.get(a)(b,c,e,f,h,l)}catch(p){Y(m);if(p!==p+0)throw p;X(1,0)}}function ec(a,b,c,e,f){var h=Z();try{return S.get(a)(b,c,e,f)}catch(l){Y(h);if(l!==l+0)throw l;X(1,0)}}w.wasmMemory=g;w.wasmExports=W;w.stackAlloc=Tb;
|
||||
w.addFunction=(a,b)=>{if(!U){U=new WeakMap;var c=S.length;if(U)for(var e=0;e<0+c;e++){var f=S.get(e);f&&U.set(f,e)}}if(c=U.get(a)||0)return c;if(Rb.length)c=Rb.pop();else{try{S.grow(1)}catch(m){if(!(m instanceof RangeError))throw m;throw"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.";}c=S.length-1}try{S.set(c,a)}catch(m){if(!(m instanceof TypeError))throw m;if("function"==typeof WebAssembly.Function){e=WebAssembly.Function;f={i:"i32",j:"i64",f:"f32",d:"f64",e:"externref",p:"i32"};for(var h={parameters:[],
|
||||
results:"v"==b[0]?[]:[f[b[0]]]},l=1;l<b.length;++l)h.parameters.push(f[b[l]]);b=new e(h,a)}else{e=[1];f=b.slice(0,1);b=b.slice(1);h={i:127,p:127,j:126,f:125,d:124,e:111};e.push(96);l=b.length;128>l?e.push(l):e.push(l%128|128,l>>7);for(l=0;l<b.length;++l)e.push(h[b[l]]);"v"==f?e.push(0):e.push(1,h[f]);b=[0,97,115,109,1,0,0,0,1];f=e.length;128>f?b.push(f):b.push(f%128|128,f>>7);b.push(...e);b.push(2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);b=new WebAssembly.Module(new Uint8Array(b));b=(new WebAssembly.Instance(b,
|
||||
{e:{f:a}})).exports.f}S.set(c,b)}U.set(a,c);return c};var mc,nc;A=function oc(){mc||pc();mc||(A=oc)};function pc(){if(!(0<z)){if(!nc&&(nc=1,Da(sa),0<z))return;mc||(mc=1,w.calledRun=1,oa||(Da(ta),ea(w),Da(ua)))}}pc();moduleRtn=ha;
|
||||
|
||||
|
||||
return moduleRtn;
|
||||
}
|
||||
);
|
||||
})();
|
||||
export default skwasm_st;
|
||||
12000
internal/form_generator/templates/canvaskit/skwasm_st.js.symbols
Normal file
BIN
internal/form_generator/templates/canvaskit/skwasm_st.wasm
Normal file
BIN
internal/form_generator/templates/favicon.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
4
internal/form_generator/templates/flutter.js
Normal file
@@ -0,0 +1,4 @@
|
||||
(()=>{var P=()=>navigator.vendor==="Google Inc."||navigator.agent==="Edg/",E=()=>typeof ImageDecoder>"u"?!1:P(),L=()=>typeof Intl.v8BreakIterator<"u"&&typeof Intl.Segmenter<"u",W=()=>{let n=[0,97,115,109,1,0,0,0,1,5,1,95,1,120,0];return WebAssembly.validate(new Uint8Array(n))},w={hasImageCodecs:E(),hasChromiumBreakIterators:L(),supportsWasmGC:W(),crossOriginIsolated:window.crossOriginIsolated};function l(...n){return new URL(C(...n),document.baseURI).toString()}function C(...n){return n.filter(t=>!!t).map((t,i)=>i===0?_(t):j(_(t))).filter(t=>t.length).join("/")}function j(n){let t=0;for(;t<n.length&&n.charAt(t)==="/";)t++;return n.substring(t)}function _(n){let t=n.length;for(;t>0&&n.charAt(t-1)==="/";)t--;return n.substring(0,t)}function T(n,t){return n.canvasKitBaseUrl?n.canvasKitBaseUrl:t.engineRevision&&!t.useLocalCanvasKit?C("https://www.gstatic.com/flutter-canvaskit",t.engineRevision):"canvaskit"}var v=class{constructor(){this._scriptLoaded=!1}setTrustedTypesPolicy(t){this._ttPolicy=t}async loadEntrypoint(t){let{entrypointUrl:i=l("main.dart.js"),onEntrypointLoaded:r,nonce:e}=t||{};return this._loadJSEntrypoint(i,r,e)}async load(t,i,r,e,a){a??=o=>{o.initializeEngine(r).then(c=>c.runApp())};let{entryPointBaseUrl:s}=r;if(t.compileTarget==="dart2wasm")return this._loadWasmEntrypoint(t,i,s,a);{let o=t.mainJsPath??"main.dart.js",c=l(s,o);return this._loadJSEntrypoint(c,a,e)}}didCreateEngineInitializer(t){typeof this._didCreateEngineInitializerResolve=="function"&&(this._didCreateEngineInitializerResolve(t),this._didCreateEngineInitializerResolve=null,delete _flutter.loader.didCreateEngineInitializer),typeof this._onEntrypointLoaded=="function"&&this._onEntrypointLoaded(t)}_loadJSEntrypoint(t,i,r){let e=typeof i=="function";if(!this._scriptLoaded){this._scriptLoaded=!0;let a=this._createScriptTag(t,r);if(e)console.debug("Injecting <script> tag. Using callback."),this._onEntrypointLoaded=i,document.head.append(a);else return new Promise((s,o)=>{console.debug("Injecting <script> tag. Using Promises. Use the callback approach instead!"),this._didCreateEngineInitializerResolve=s,a.addEventListener("error",o),document.head.append(a)})}}async _loadWasmEntrypoint(t,i,r,e){if(!this._scriptLoaded){this._scriptLoaded=!0,this._onEntrypointLoaded=e;let{mainWasmPath:a,jsSupportRuntimePath:s}=t,o=l(r,a),c=l(r,s);this._ttPolicy!=null&&(c=this._ttPolicy.createScriptURL(c));let d=(await import(c)).compileStreaming(fetch(o)),f;t.renderer==="skwasm"?f=(async()=>{let m=await i.skwasm;return window._flutter_skwasmInstance=m,{skwasm:m.wasmExports,skwasmWrapper:m,ffi:{memory:m.wasmMemory}}})():f=Promise.resolve({}),await(await(await d).instantiate(await f)).invokeMain()}}_createScriptTag(t,i){let r=document.createElement("script");r.type="application/javascript",i&&(r.nonce=i);let e=t;return this._ttPolicy!=null&&(e=this._ttPolicy.createScriptURL(t)),r.src=e,r}};async function I(n,t,i){if(t<0)return n;let r,e=new Promise((a,s)=>{r=setTimeout(()=>{s(new Error(`${i} took more than ${t}ms to resolve. Moving on.`,{cause:I}))},t)});return Promise.race([n,e]).finally(()=>{clearTimeout(r)})}var y=class{setTrustedTypesPolicy(t){this._ttPolicy=t}loadServiceWorker(t){if(!t)return console.debug("Null serviceWorker configuration. Skipping."),Promise.resolve();if(!("serviceWorker"in navigator)){let o="Service Worker API unavailable.";return window.isSecureContext||(o+=`
|
||||
The current context is NOT secure.`,o+=`
|
||||
Read more: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts`),Promise.reject(new Error(o))}let{serviceWorkerVersion:i,serviceWorkerUrl:r=l(`flutter_service_worker.js?v=${i}`),timeoutMillis:e=4e3}=t,a=r;this._ttPolicy!=null&&(a=this._ttPolicy.createScriptURL(a));let s=navigator.serviceWorker.register(a).then(o=>this._getNewServiceWorker(o,i)).then(this._waitForServiceWorkerActivation);return I(s,e,"prepareServiceWorker")}async _getNewServiceWorker(t,i){if(!t.active&&(t.installing||t.waiting))return console.debug("Installing/Activating first service worker."),t.installing||t.waiting;if(t.active.scriptURL.endsWith(i))return console.debug("Loading from existing service worker."),t.active;{let r=await t.update();return console.debug("Updating service worker."),r.installing||r.waiting||r.active}}async _waitForServiceWorkerActivation(t){if(!t||t.state==="activated")if(t){console.debug("Service worker already active.");return}else throw new Error("Cannot activate a null service worker!");return new Promise((i,r)=>{t.addEventListener("statechange",()=>{t.state==="activated"&&(console.debug("Activated new service worker."),i())})})}};var g=class{constructor(t,i="flutter-js"){let r=t||[/\.js$/,/\.mjs$/];window.trustedTypes&&(this.policy=trustedTypes.createPolicy(i,{createScriptURL:function(e){if(e.startsWith("blob:"))return e;let a=new URL(e,window.location),s=a.pathname.split("/").pop();if(r.some(c=>c.test(s)))return a.toString();console.error("URL rejected by TrustedTypes policy",i,":",e,"(download prevented)")}}))}};var k=n=>{let t=WebAssembly.compileStreaming(fetch(n));return(i,r)=>((async()=>{let e=await t,a=await WebAssembly.instantiate(e,i);r(a,e)})(),{})};var b=(n,t,i,r)=>(window.flutterCanvasKitLoaded=(async()=>{if(window.flutterCanvasKit)return window.flutterCanvasKit;let e=i.hasChromiumBreakIterators&&i.hasImageCodecs;if(!e&&t.canvasKitVariant=="chromium")throw"Chromium CanvasKit variant specifically requested, but unsupported in this browser";let a=e&&t.canvasKitVariant!=="full",s=r;a&&(s=l(s,"chromium"));let o=l(s,"canvaskit.js");n.flutterTT.policy&&(o=n.flutterTT.policy.createScriptURL(o));let c=k(l(s,"canvaskit.wasm")),p=await import(o);return window.flutterCanvasKit=await p.default({instantiateWasm:c}),window.flutterCanvasKit})(),window.flutterCanvasKitLoaded);var U=async(n,t,i,r)=>{let e=i.crossOriginIsolated&&!t.forceSingleThreadedSkwasm?"skwasm":"skwasm_st",s=l(r,`${e}.js`);n.flutterTT.policy&&(s=n.flutterTT.policy.createScriptURL(s));let o=k(l(r,`${e}.wasm`));return await(await import(s)).default({instantiateWasm:o,mainScriptUrlOrBlob:new Blob([`import '${s}'`],{type:"application/javascript"})})};var S=class{async loadEntrypoint(t){let{serviceWorker:i,...r}=t||{},e=new g,a=new y;a.setTrustedTypesPolicy(e.policy),await a.loadServiceWorker(i).catch(o=>{console.warn("Exception while loading service worker:",o)});let s=new v;return s.setTrustedTypesPolicy(e.policy),this.didCreateEngineInitializer=s.didCreateEngineInitializer.bind(s),s.loadEntrypoint(r)}async load({serviceWorkerSettings:t,onEntrypointLoaded:i,nonce:r,config:e}={}){e??={};let a=_flutter.buildConfig;if(!a)throw"FlutterLoader.load requires _flutter.buildConfig to be set";let s=u=>{switch(u){case"skwasm":return w.hasChromiumBreakIterators&&w.hasImageCodecs&&w.supportsWasmGC;default:return!0}},o=(u,m)=>{switch(u.renderer){case"auto":return m=="canvaskit"||m=="html";default:return u.renderer==m}},c=u=>u.compileTarget==="dart2wasm"&&!w.supportsWasmGC||e.renderer&&!o(u,e.renderer)?!1:s(u.renderer),p=a.builds.find(c);if(!p)throw"FlutterLoader could not find a build compatible with configuration and environment.";let d={};d.flutterTT=new g,t&&(d.serviceWorkerLoader=new y,d.serviceWorkerLoader.setTrustedTypesPolicy(d.flutterTT.policy),await d.serviceWorkerLoader.loadServiceWorker(t).catch(u=>{console.warn("Exception while loading service worker:",u)}));let f=T(e,a);p.renderer==="canvaskit"?d.canvasKit=b(d,e,w,f):p.renderer==="skwasm"&&(d.skwasm=U(d,e,w,f));let h=new v;return h.setTrustedTypesPolicy(d.flutterTT.policy),this.didCreateEngineInitializer=h.didCreateEngineInitializer.bind(h),h.load(p,d,e,r,i)}};window._flutter||(window._flutter={});window._flutter.loader||(window._flutter.loader=new S);})();
|
||||
//# sourceMappingURL=flutter.js.map
|
||||
16
internal/form_generator/templates/flutter_bootstrap.js
Normal file
@@ -0,0 +1,16 @@
|
||||
(()=>{var P=()=>navigator.vendor==="Google Inc."||navigator.agent==="Edg/",E=()=>typeof ImageDecoder>"u"?!1:P(),L=()=>typeof Intl.v8BreakIterator<"u"&&typeof Intl.Segmenter<"u",W=()=>{let n=[0,97,115,109,1,0,0,0,1,5,1,95,1,120,0];return WebAssembly.validate(new Uint8Array(n))},w={hasImageCodecs:E(),hasChromiumBreakIterators:L(),supportsWasmGC:W(),crossOriginIsolated:window.crossOriginIsolated};function l(...n){return new URL(C(...n),document.baseURI).toString()}function C(...n){return n.filter(t=>!!t).map((t,i)=>i===0?_(t):j(_(t))).filter(t=>t.length).join("/")}function j(n){let t=0;for(;t<n.length&&n.charAt(t)==="/";)t++;return n.substring(t)}function _(n){let t=n.length;for(;t>0&&n.charAt(t-1)==="/";)t--;return n.substring(0,t)}function T(n,t){return n.canvasKitBaseUrl?n.canvasKitBaseUrl:t.engineRevision&&!t.useLocalCanvasKit?C("https://www.gstatic.com/flutter-canvaskit",t.engineRevision):"canvaskit"}var v=class{constructor(){this._scriptLoaded=!1}setTrustedTypesPolicy(t){this._ttPolicy=t}async loadEntrypoint(t){let{entrypointUrl:i=l("main.dart.js"),onEntrypointLoaded:r,nonce:e}=t||{};return this._loadJSEntrypoint(i,r,e)}async load(t,i,r,e,a){a??=o=>{o.initializeEngine(r).then(c=>c.runApp())};let{entryPointBaseUrl:s}=r;if(t.compileTarget==="dart2wasm")return this._loadWasmEntrypoint(t,i,s,a);{let o=t.mainJsPath??"main.dart.js",c=l(s,o);return this._loadJSEntrypoint(c,a,e)}}didCreateEngineInitializer(t){typeof this._didCreateEngineInitializerResolve=="function"&&(this._didCreateEngineInitializerResolve(t),this._didCreateEngineInitializerResolve=null,delete _flutter.loader.didCreateEngineInitializer),typeof this._onEntrypointLoaded=="function"&&this._onEntrypointLoaded(t)}_loadJSEntrypoint(t,i,r){let e=typeof i=="function";if(!this._scriptLoaded){this._scriptLoaded=!0;let a=this._createScriptTag(t,r);if(e)console.debug("Injecting <script> tag. Using callback."),this._onEntrypointLoaded=i,document.head.append(a);else return new Promise((s,o)=>{console.debug("Injecting <script> tag. Using Promises. Use the callback approach instead!"),this._didCreateEngineInitializerResolve=s,a.addEventListener("error",o),document.head.append(a)})}}async _loadWasmEntrypoint(t,i,r,e){if(!this._scriptLoaded){this._scriptLoaded=!0,this._onEntrypointLoaded=e;let{mainWasmPath:a,jsSupportRuntimePath:s}=t,o=l(r,a),c=l(r,s);this._ttPolicy!=null&&(c=this._ttPolicy.createScriptURL(c));let d=(await import(c)).compileStreaming(fetch(o)),f;t.renderer==="skwasm"?f=(async()=>{let m=await i.skwasm;return window._flutter_skwasmInstance=m,{skwasm:m.wasmExports,skwasmWrapper:m,ffi:{memory:m.wasmMemory}}})():f=Promise.resolve({}),await(await(await d).instantiate(await f)).invokeMain()}}_createScriptTag(t,i){let r=document.createElement("script");r.type="application/javascript",i&&(r.nonce=i);let e=t;return this._ttPolicy!=null&&(e=this._ttPolicy.createScriptURL(t)),r.src=e,r}};async function I(n,t,i){if(t<0)return n;let r,e=new Promise((a,s)=>{r=setTimeout(()=>{s(new Error(`${i} took more than ${t}ms to resolve. Moving on.`,{cause:I}))},t)});return Promise.race([n,e]).finally(()=>{clearTimeout(r)})}var y=class{setTrustedTypesPolicy(t){this._ttPolicy=t}loadServiceWorker(t){if(!t)return console.debug("Null serviceWorker configuration. Skipping."),Promise.resolve();if(!("serviceWorker"in navigator)){let o="Service Worker API unavailable.";return window.isSecureContext||(o+=`
|
||||
The current context is NOT secure.`,o+=`
|
||||
Read more: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts`),Promise.reject(new Error(o))}let{serviceWorkerVersion:i,serviceWorkerUrl:r=l(`flutter_service_worker.js?v=${i}`),timeoutMillis:e=4e3}=t,a=r;this._ttPolicy!=null&&(a=this._ttPolicy.createScriptURL(a));let s=navigator.serviceWorker.register(a).then(o=>this._getNewServiceWorker(o,i)).then(this._waitForServiceWorkerActivation);return I(s,e,"prepareServiceWorker")}async _getNewServiceWorker(t,i){if(!t.active&&(t.installing||t.waiting))return console.debug("Installing/Activating first service worker."),t.installing||t.waiting;if(t.active.scriptURL.endsWith(i))return console.debug("Loading from existing service worker."),t.active;{let r=await t.update();return console.debug("Updating service worker."),r.installing||r.waiting||r.active}}async _waitForServiceWorkerActivation(t){if(!t||t.state==="activated")if(t){console.debug("Service worker already active.");return}else throw new Error("Cannot activate a null service worker!");return new Promise((i,r)=>{t.addEventListener("statechange",()=>{t.state==="activated"&&(console.debug("Activated new service worker."),i())})})}};var g=class{constructor(t,i="flutter-js"){let r=t||[/\.js$/,/\.mjs$/];window.trustedTypes&&(this.policy=trustedTypes.createPolicy(i,{createScriptURL:function(e){if(e.startsWith("blob:"))return e;let a=new URL(e,window.location),s=a.pathname.split("/").pop();if(r.some(c=>c.test(s)))return a.toString();console.error("URL rejected by TrustedTypes policy",i,":",e,"(download prevented)")}}))}};var k=n=>{let t=WebAssembly.compileStreaming(fetch(n));return(i,r)=>((async()=>{let e=await t,a=await WebAssembly.instantiate(e,i);r(a,e)})(),{})};var b=(n,t,i,r)=>(window.flutterCanvasKitLoaded=(async()=>{if(window.flutterCanvasKit)return window.flutterCanvasKit;let e=i.hasChromiumBreakIterators&&i.hasImageCodecs;if(!e&&t.canvasKitVariant=="chromium")throw"Chromium CanvasKit variant specifically requested, but unsupported in this browser";let a=e&&t.canvasKitVariant!=="full",s=r;a&&(s=l(s,"chromium"));let o=l(s,"canvaskit.js");n.flutterTT.policy&&(o=n.flutterTT.policy.createScriptURL(o));let c=k(l(s,"canvaskit.wasm")),p=await import(o);return window.flutterCanvasKit=await p.default({instantiateWasm:c}),window.flutterCanvasKit})(),window.flutterCanvasKitLoaded);var U=async(n,t,i,r)=>{let e=i.crossOriginIsolated&&!t.forceSingleThreadedSkwasm?"skwasm":"skwasm_st",s=l(r,`${e}.js`);n.flutterTT.policy&&(s=n.flutterTT.policy.createScriptURL(s));let o=k(l(r,`${e}.wasm`));return await(await import(s)).default({instantiateWasm:o,mainScriptUrlOrBlob:new Blob([`import '${s}'`],{type:"application/javascript"})})};var S=class{async loadEntrypoint(t){let{serviceWorker:i,...r}=t||{},e=new g,a=new y;a.setTrustedTypesPolicy(e.policy),await a.loadServiceWorker(i).catch(o=>{console.warn("Exception while loading service worker:",o)});let s=new v;return s.setTrustedTypesPolicy(e.policy),this.didCreateEngineInitializer=s.didCreateEngineInitializer.bind(s),s.loadEntrypoint(r)}async load({serviceWorkerSettings:t,onEntrypointLoaded:i,nonce:r,config:e}={}){e??={};let a=_flutter.buildConfig;if(!a)throw"FlutterLoader.load requires _flutter.buildConfig to be set";let s=u=>{switch(u){case"skwasm":return w.hasChromiumBreakIterators&&w.hasImageCodecs&&w.supportsWasmGC;default:return!0}},o=(u,m)=>{switch(u.renderer){case"auto":return m=="canvaskit"||m=="html";default:return u.renderer==m}},c=u=>u.compileTarget==="dart2wasm"&&!w.supportsWasmGC||e.renderer&&!o(u,e.renderer)?!1:s(u.renderer),p=a.builds.find(c);if(!p)throw"FlutterLoader could not find a build compatible with configuration and environment.";let d={};d.flutterTT=new g,t&&(d.serviceWorkerLoader=new y,d.serviceWorkerLoader.setTrustedTypesPolicy(d.flutterTT.policy),await d.serviceWorkerLoader.loadServiceWorker(t).catch(u=>{console.warn("Exception while loading service worker:",u)}));let f=T(e,a);p.renderer==="canvaskit"?d.canvasKit=b(d,e,w,f):p.renderer==="skwasm"&&(d.skwasm=U(d,e,w,f));let h=new v;return h.setTrustedTypesPolicy(d.flutterTT.policy),this.didCreateEngineInitializer=h.didCreateEngineInitializer.bind(h),h.load(p,d,e,r,i)}};window._flutter||(window._flutter={});window._flutter.loader||(window._flutter.loader=new S);})();
|
||||
//# sourceMappingURL=flutter.js.map
|
||||
|
||||
if (!window._flutter) {
|
||||
window._flutter = {};
|
||||
}
|
||||
_flutter.buildConfig = {"engineRevision":"18b71d647a292a980abb405ac7d16fe1f0b20434","builds":[{"compileTarget":"dart2js","renderer":"canvaskit","mainJsPath":"main.dart.js"}]};
|
||||
|
||||
|
||||
_flutter.loader.load({
|
||||
serviceWorkerSettings: {
|
||||
serviceWorkerVersion: "2389281828"
|
||||
}
|
||||
});
|
||||
218
internal/form_generator/templates/flutter_service_worker.js
Normal file
@@ -0,0 +1,218 @@
|
||||
'use strict';
|
||||
const MANIFEST = 'flutter-app-manifest';
|
||||
const TEMP = 'flutter-temp-cache';
|
||||
const CACHE_NAME = 'flutter-app-cache';
|
||||
|
||||
const RESOURCES = {"icons/Icon-maskable-512.png": "301a7604d45b3e739efc881eb04896ea",
|
||||
"icons/Icon-maskable-192.png": "c457ef57daa1d16f64b27b786ec2ea3c",
|
||||
"icons/Icon-512.png": "bc48e3cc3e85ab2b0d0ef914b4a6e382",
|
||||
"icons/Icon-192.png": "3b057a05d8abc1604131b4bf70f7fd78",
|
||||
"flutter.js": "76f08d47ff9f5715220992f993002504",
|
||||
"index.html": "59c5932948135921d6bc7f653a605a17",
|
||||
"/": "59c5932948135921d6bc7f653a605a17",
|
||||
"favicon.png": "f32d5e86fa0e4006e9f570d17ee57a0b",
|
||||
"version.json": "1bee6108c0b137ad55b03d38a79bba11",
|
||||
"canvaskit/skwasm_st.wasm": "56c3973560dfcbf28ce47cebe40f3206",
|
||||
"canvaskit/skwasm.js.symbols": "80806576fa1056b43dd6d0b445b4b6f7",
|
||||
"canvaskit/skwasm.js": "f2ad9363618c5f62e813740099a80e63",
|
||||
"canvaskit/skwasm_st.js": "d1326ceef381ad382ab492ba5d96f04d",
|
||||
"canvaskit/chromium/canvaskit.js.symbols": "5a23598a2a8efd18ec3b60de5d28af8f",
|
||||
"canvaskit/chromium/canvaskit.js": "34beda9f39eb7d992d46125ca868dc61",
|
||||
"canvaskit/chromium/canvaskit.wasm": "64a386c87532ae52ae041d18a32a3635",
|
||||
"canvaskit/canvaskit.js.symbols": "68eb703b9a609baef8ee0e413b442f33",
|
||||
"canvaskit/canvaskit.js": "86e461cf471c1640fd2b461ece4589df",
|
||||
"canvaskit/canvaskit.wasm": "efeeba7dcc952dae57870d4df3111fad",
|
||||
"canvaskit/skwasm.wasm": "f0dfd99007f989368db17c9abeed5a49",
|
||||
"canvaskit/skwasm_st.js.symbols": "c7e7aac7cd8b612defd62b43e3050bdd",
|
||||
"assets/AssetManifest.bin.json": "804bafee7f3e2d49cef2cd7975a139c6",
|
||||
"assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "33b7d9392238c04c131b6ce224e13711",
|
||||
"assets/packages/quickalert/assets/success.gif": "dcede9f3064fe66b69f7bbe7b6e3849f",
|
||||
"assets/packages/quickalert/assets/loading.gif": "ac70f280e4a1b90065fe981eafe8ae13",
|
||||
"assets/packages/quickalert/assets/confirm.gif": "bdc3e511c73e97fbc5cfb0c2b5f78e00",
|
||||
"assets/packages/quickalert/assets/warning.gif": "f45dfa3b5857b812e0c8227211635cc4",
|
||||
"assets/packages/quickalert/assets/error.gif": "c307db003cf53e131f1c704bb16fb9bf",
|
||||
"assets/packages/quickalert/assets/info.gif": "90d7fface6e2d52554f8614a1f5deb6b",
|
||||
"assets/fonts/MaterialIcons-Regular.otf": "d40aed5a68282e4bd529de589ab20804",
|
||||
"assets/AssetManifest.json": "a8ca1f71d3c77c4128047a86775cd5c1",
|
||||
"assets/assets/favicon.png": "d5fb3b7c82e3233517e880ef62b755c9",
|
||||
"assets/assets/images/send.svg": "e38b31ea755d9555fb44d7e9b03db490",
|
||||
"assets/assets/images/resume-link.svg": "71232d92bdd73c2697243ca911451540",
|
||||
"assets/assets/images/resume-file.svg": "1075e32928d6fdfbe4e488d326abaf3e",
|
||||
"assets/assets/images/logo.svg": "66054164ee6d5dc3afd4eacd99db80e3",
|
||||
"assets/FontManifest.json": "dc3d03800ccca4601324923c0b1d6d57",
|
||||
"assets/shaders/ink_sparkle.frag": "ecc85a2e95f5e9f53123dcaf8cb9b6ce",
|
||||
"assets/AssetManifest.bin": "d8837089cad8dcd9a4f7508d831c6370",
|
||||
"assets/NOTICES": "30019a615949ce7923021e851dcdf776",
|
||||
"manifest.json": "eedecdf540009c5b146d53466f940cf5",
|
||||
"flutter_bootstrap.js": "f4f69d8e0ddb330c26b1f94cd0c3011f",
|
||||
"main.dart.js": "43b25bdf7d31c1789a09fabd3d00baac"};
|
||||
// The application shell files that are downloaded before a service worker can
|
||||
// start.
|
||||
const CORE = ["main.dart.js",
|
||||
"index.html",
|
||||
"flutter_bootstrap.js",
|
||||
"assets/AssetManifest.bin.json",
|
||||
"assets/FontManifest.json"];
|
||||
|
||||
// During install, the TEMP cache is populated with the application shell files.
|
||||
self.addEventListener("install", (event) => {
|
||||
self.skipWaiting();
|
||||
return event.waitUntil(
|
||||
caches.open(TEMP).then((cache) => {
|
||||
return cache.addAll(
|
||||
CORE.map((value) => new Request(value, {'cache': 'reload'})));
|
||||
})
|
||||
);
|
||||
});
|
||||
// During activate, the cache is populated with the temp files downloaded in
|
||||
// install. If this service worker is upgrading from one with a saved
|
||||
// MANIFEST, then use this to retain unchanged resource files.
|
||||
self.addEventListener("activate", function(event) {
|
||||
return event.waitUntil(async function() {
|
||||
try {
|
||||
var contentCache = await caches.open(CACHE_NAME);
|
||||
var tempCache = await caches.open(TEMP);
|
||||
var manifestCache = await caches.open(MANIFEST);
|
||||
var manifest = await manifestCache.match('manifest');
|
||||
// When there is no prior manifest, clear the entire cache.
|
||||
if (!manifest) {
|
||||
await caches.delete(CACHE_NAME);
|
||||
contentCache = await caches.open(CACHE_NAME);
|
||||
for (var request of await tempCache.keys()) {
|
||||
var response = await tempCache.match(request);
|
||||
await contentCache.put(request, response);
|
||||
}
|
||||
await caches.delete(TEMP);
|
||||
// Save the manifest to make future upgrades efficient.
|
||||
await manifestCache.put('manifest', new Response(JSON.stringify(RESOURCES)));
|
||||
// Claim client to enable caching on first launch
|
||||
self.clients.claim();
|
||||
return;
|
||||
}
|
||||
var oldManifest = await manifest.json();
|
||||
var origin = self.location.origin;
|
||||
for (var request of await contentCache.keys()) {
|
||||
var key = request.url.substring(origin.length + 1);
|
||||
if (key == "") {
|
||||
key = "/";
|
||||
}
|
||||
// If a resource from the old manifest is not in the new cache, or if
|
||||
// the MD5 sum has changed, delete it. Otherwise the resource is left
|
||||
// in the cache and can be reused by the new service worker.
|
||||
if (!RESOURCES[key] || RESOURCES[key] != oldManifest[key]) {
|
||||
await contentCache.delete(request);
|
||||
}
|
||||
}
|
||||
// Populate the cache with the app shell TEMP files, potentially overwriting
|
||||
// cache files preserved above.
|
||||
for (var request of await tempCache.keys()) {
|
||||
var response = await tempCache.match(request);
|
||||
await contentCache.put(request, response);
|
||||
}
|
||||
await caches.delete(TEMP);
|
||||
// Save the manifest to make future upgrades efficient.
|
||||
await manifestCache.put('manifest', new Response(JSON.stringify(RESOURCES)));
|
||||
// Claim client to enable caching on first launch
|
||||
self.clients.claim();
|
||||
return;
|
||||
} catch (err) {
|
||||
// On an unhandled exception the state of the cache cannot be guaranteed.
|
||||
console.error('Failed to upgrade service worker: ' + err);
|
||||
await caches.delete(CACHE_NAME);
|
||||
await caches.delete(TEMP);
|
||||
await caches.delete(MANIFEST);
|
||||
}
|
||||
}());
|
||||
});
|
||||
// The fetch handler redirects requests for RESOURCE files to the service
|
||||
// worker cache.
|
||||
self.addEventListener("fetch", (event) => {
|
||||
if (event.request.method !== 'GET') {
|
||||
return;
|
||||
}
|
||||
var origin = self.location.origin;
|
||||
var key = event.request.url.substring(origin.length + 1);
|
||||
// Redirect URLs to the index.html
|
||||
if (key.indexOf('?v=') != -1) {
|
||||
key = key.split('?v=')[0];
|
||||
}
|
||||
if (event.request.url == origin || event.request.url.startsWith(origin + '/#') || key == '') {
|
||||
key = '/';
|
||||
}
|
||||
// If the URL is not the RESOURCE list then return to signal that the
|
||||
// browser should take over.
|
||||
if (!RESOURCES[key]) {
|
||||
return;
|
||||
}
|
||||
// If the URL is the index.html, perform an online-first request.
|
||||
if (key == '/') {
|
||||
return onlineFirst(event);
|
||||
}
|
||||
event.respondWith(caches.open(CACHE_NAME)
|
||||
.then((cache) => {
|
||||
return cache.match(event.request).then((response) => {
|
||||
// Either respond with the cached resource, or perform a fetch and
|
||||
// lazily populate the cache only if the resource was successfully fetched.
|
||||
return response || fetch(event.request).then((response) => {
|
||||
if (response && Boolean(response.ok)) {
|
||||
cache.put(event.request, response.clone());
|
||||
}
|
||||
return response;
|
||||
});
|
||||
})
|
||||
})
|
||||
);
|
||||
});
|
||||
self.addEventListener('message', (event) => {
|
||||
// SkipWaiting can be used to immediately activate a waiting service worker.
|
||||
// This will also require a page refresh triggered by the main worker.
|
||||
if (event.data === 'skipWaiting') {
|
||||
self.skipWaiting();
|
||||
return;
|
||||
}
|
||||
if (event.data === 'downloadOffline') {
|
||||
downloadOffline();
|
||||
return;
|
||||
}
|
||||
});
|
||||
// Download offline will check the RESOURCES for all files not in the cache
|
||||
// and populate them.
|
||||
async function downloadOffline() {
|
||||
var resources = [];
|
||||
var contentCache = await caches.open(CACHE_NAME);
|
||||
var currentContent = {};
|
||||
for (var request of await contentCache.keys()) {
|
||||
var key = request.url.substring(origin.length + 1);
|
||||
if (key == "") {
|
||||
key = "/";
|
||||
}
|
||||
currentContent[key] = true;
|
||||
}
|
||||
for (var resourceKey of Object.keys(RESOURCES)) {
|
||||
if (!currentContent[resourceKey]) {
|
||||
resources.push(resourceKey);
|
||||
}
|
||||
}
|
||||
return contentCache.addAll(resources);
|
||||
}
|
||||
// Attempt to download the resource online before falling back to
|
||||
// the offline cache.
|
||||
function onlineFirst(event) {
|
||||
return event.respondWith(
|
||||
fetch(event.request).then((response) => {
|
||||
return caches.open(CACHE_NAME).then((cache) => {
|
||||
cache.put(event.request, response.clone());
|
||||
return response;
|
||||
});
|
||||
}).catch((error) => {
|
||||
return caches.open(CACHE_NAME).then((cache) => {
|
||||
return cache.match(event.request).then((response) => {
|
||||
if (response != null) {
|
||||
return response;
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
BIN
internal/form_generator/templates/icons/Icon-192.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
internal/form_generator/templates/icons/Icon-512.png
Normal file
|
After Width: | Height: | Size: 194 KiB |
BIN
internal/form_generator/templates/icons/Icon-maskable-192.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
internal/form_generator/templates/icons/Icon-maskable-512.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
54
internal/form_generator/templates/index.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<!--
|
||||
If you are serving your web app in a path other than the root, change the
|
||||
href value below to reflect the base path you are serving from.
|
||||
|
||||
The path provided below has to start and end with a slash "/" in order for
|
||||
it to work correctly.
|
||||
|
||||
For more details:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
||||
|
||||
This is a placeholder for base href that will be replaced by the value of
|
||||
the `--base-href` argument provided to `flutter build`.
|
||||
-->
|
||||
<base href="/api/v1/anketa/static/">
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="description" content="A new Flutter project.">
|
||||
|
||||
<!-- iOS meta tags & icons -->
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="client_form">
|
||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
|
||||
<title>client_form</title>
|
||||
<link rel="manifest" href="manifest.json">
|
||||
|
||||
<script>
|
||||
window.agentID = "{{.AgentId}}";
|
||||
window.vacancyID = "{{.VacancyId}}";
|
||||
window.vacancyName = "{{.VacancyName}}";
|
||||
window.vacancyAddress = "{{.Address}}";
|
||||
window.vacancyWorkFormat = "{{.WorkFormat}}";
|
||||
window.vacancySalaryTop = "{{.SalaryTop}}";
|
||||
window.vacancySalaryBottom = "{{.SalaryBottom}}";
|
||||
window.vacancyRequirements = "{{.Requirements}}";
|
||||
window.vacancyResponsibilities = "{{.Responsibilities}}";
|
||||
window.vacancyDescription = "{{.Description}}";
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src="flutter_bootstrap.js" async></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
94967
internal/form_generator/templates/main.dart.js
Normal file
35
internal/form_generator/templates/manifest.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "client_form",
|
||||
"short_name": "client_form",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"background_color": "#0175C2",
|
||||
"theme_color": "#0175C2",
|
||||
"description": "A new Flutter project.",
|
||||
"orientation": "portrait-primary",
|
||||
"prefer_related_applications": false,
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/Icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
1
internal/form_generator/templates/version.json
Normal file
@@ -0,0 +1 @@
|
||||
{"app_name":"client_form","version":"1.0.0","build_number":"1","package_name":"client_form"}
|
||||
557
internal/http/auth.go
Normal file
@@ -0,0 +1,557 @@
|
||||
package http_router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/auth"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/auth/keycloak"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/broker"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
|
||||
dbtypes "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/types"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/feed"
|
||||
notification "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/notifications/git-molva.ru/Molva/molva-notification-service"
|
||||
rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model"
|
||||
authinfra "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/services/auth_infrastructure"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// ------------------------------
|
||||
// LOGIN USER
|
||||
// ------------------------------
|
||||
|
||||
func (h *handler) loginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "loginHandler"
|
||||
|
||||
var request rmodel.LoginUserRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("Invalid request body",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
defer func(body io.ReadCloser) {
|
||||
if err := body.Close(); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error closing body",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}(r.Body)
|
||||
|
||||
tokens, err := h.authManager.LoginUser(r.Context(), auth.LoginUserRequest{
|
||||
Email: request.Email,
|
||||
Password: request.Password,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleKeycloakError(w, err)
|
||||
h.logger.Error("error while login user",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
userInfo, err := h.authManager.GetUserInfo(r.Context(), tokens.UserId)
|
||||
if err != nil {
|
||||
h.handleKeycloakError(w, err)
|
||||
h.logger.Error("error while getting user info",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
emailVerificationStatus, err := h.authManager.GetEmailVerificationStatus(r.Context(), tokens.UserId)
|
||||
if err != nil {
|
||||
h.handleKeycloakError(w, err)
|
||||
h.logger.Error("error while getting email verification status",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err = json.NewEncoder(w).Encode(rmodel.LoginUserResponse{
|
||||
Uid: tokens.UserId,
|
||||
AccessToken: tokens.AccessToken,
|
||||
RefreshToken: tokens.RefreshToken,
|
||||
UserType: userInfo.UserType,
|
||||
Permissions: rmodel.Permissions{
|
||||
Balance: userInfo.Permissions[keycloak.PermissionBalance],
|
||||
Company: userInfo.Permissions[keycloak.PermissionCompany],
|
||||
Employees: userInfo.Permissions[keycloak.PermissionEmployees],
|
||||
Profile: userInfo.Permissions[keycloak.PermissionProfile],
|
||||
Submissions: userInfo.Permissions[keycloak.PermissionSubmissions],
|
||||
Vacancies: userInfo.Permissions[keycloak.PermissionVacancies],
|
||||
},
|
||||
EmailVerified: emailVerificationStatus.EmailVerified,
|
||||
}); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error while encoding response: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// REGISTER USER
|
||||
// ------------------------------
|
||||
|
||||
func (h *handler) registerHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "registerHandler"
|
||||
|
||||
var creds rmodel.UserCredentials
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error decoding request body",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
defer r.Body.Close()
|
||||
|
||||
if h.env == "production" {
|
||||
isEmailValid, err := h.validateEmail(creds.Email)
|
||||
if err != nil {
|
||||
h.logger.Warn("EmailVerificationService API service error, proceeding with email validation via message",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("email", creds.Email),
|
||||
slog.String("handler", handlerName))
|
||||
} else if !isEmailValid {
|
||||
h.logger.Warn("email validation failed - invalid email address",
|
||||
slog.String("email", creds.Email),
|
||||
slog.String("handler", handlerName))
|
||||
http.Error(w, "Invalid email address", http.StatusBadRequest)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
uid, err := h.authManager.RegisterUser(r.Context(), auth.RegisterUserRequest{
|
||||
User: auth.User{
|
||||
Email: creds.Email,
|
||||
Password: creds.Password,
|
||||
FirstName: creds.FirstName,
|
||||
SecondName: creds.LastName,
|
||||
Patronymic: creds.MiddleName,
|
||||
Number: creds.PhoneNumber,
|
||||
Permissions: creds.Permissions,
|
||||
},
|
||||
UserType: creds.UserType,
|
||||
})
|
||||
if err != nil {
|
||||
h.logger.Error("error while saving user to keycloak",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
h.handleKeycloakError(w, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.saveUser(r.Context(), uid.UserId, creds); err != nil {
|
||||
h.handleDBError(w, err)
|
||||
h.logger.Error("error saving user to DB",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
tokenResp, err := h.authManager.GetUserEmailVerificationToken(r.Context(), uid.UserId)
|
||||
if err != nil {
|
||||
h.logger.Error("error getting user token",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
userName := formatName(creds.LastName, creds.FirstName, creds.MiddleName)
|
||||
|
||||
if err := h.sendConfirmationEmail(r, creds.Email, userName, uid.UserId, tokenResp.AccessToken); err != nil {
|
||||
h.logger.Error("error sending confirmation email",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
h.createWelcomeEvent(r.Context(), uid.UserId, creds, handlerName)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
|
||||
if err := json.NewEncoder(w).Encode(&rmodel.RegisterResponse{UUID: uid.UserId}); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error while encoding response", slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createWelcomeEvent(ctx context.Context, userID string, creds rmodel.UserCredentials, handlerName string) {
|
||||
ownerType := feed.RoleAgent
|
||||
if creds.UserType == constants.DistributorClientType {
|
||||
ownerType = feed.RoleDistributor
|
||||
}
|
||||
|
||||
event := feed.Event{
|
||||
OwnerId: userID,
|
||||
OwnerType: ownerType,
|
||||
EventType: feed.EventWelcome,
|
||||
Message: "Добро пожаловать в Molva!",
|
||||
Visibility: feed.VisibilityPrivate,
|
||||
Payload: feed.EventPayload{},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("uid", userID))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) sendConfirmationEmail(r *http.Request, email, userName, userID, accessToken string) error {
|
||||
scheme := "https"
|
||||
if r.TLS == nil {
|
||||
scheme = "http"
|
||||
}
|
||||
|
||||
confirmURL := fmt.Sprintf("%s://%s/api/v1/confirm_email?uid=%s&token=%s",
|
||||
scheme,
|
||||
r.Host,
|
||||
url.QueryEscape(userID),
|
||||
url.QueryEscape(accessToken),
|
||||
)
|
||||
|
||||
emailBody := fmt.Sprintf(constants.EmailVerificationTemplate,
|
||||
userName,
|
||||
confirmURL,
|
||||
confirmURL,
|
||||
)
|
||||
|
||||
msg, err := proto.Marshal(¬ification.SendEmailRequest{
|
||||
To: []string{email},
|
||||
Subject: constants.EmailVerificationMessageSubject,
|
||||
ContentType: constants.HTMLNotificationContentType,
|
||||
Body: []byte(emailBody),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshaling email message: %w", err)
|
||||
}
|
||||
|
||||
if err := broker.SendNotification(
|
||||
broker.NotificationQueue,
|
||||
constants.EmailNotificationMessageType,
|
||||
msg,
|
||||
h.logger,
|
||||
); err != nil {
|
||||
return fmt.Errorf("sending notification: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NOTE: lastName and firstName are required to be non-empty
|
||||
func formatName(lastName, firstName string, middleName *string) string {
|
||||
name := fmt.Sprintf("%s %s", lastName, firstName)
|
||||
|
||||
if middleName != nil {
|
||||
name = fmt.Sprintf("%s %s", name, *middleName)
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
func (h *handler) saveUser(ctx context.Context, uid string, creds rmodel.UserCredentials) error {
|
||||
userName := formatName(creds.LastName, creds.FirstName, creds.MiddleName)
|
||||
|
||||
if _, err := h.dbClient.CreateUser(ctx, &dbtypes.UserSaveRequest{
|
||||
Id: uid,
|
||||
FullName: userName,
|
||||
Phone: creds.PhoneNumber,
|
||||
Email: creds.Email,
|
||||
Type: dbtypes.UserType(creds.UserType),
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// LOGOUT USER
|
||||
// ------------------------------
|
||||
|
||||
func (h *handler) logoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "logoutHandler"
|
||||
|
||||
var request rmodel.LogoutUserRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while decoding request body: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.authManager.LogoutUser(r.Context(), auth.LogoutUserRequest{
|
||||
RefreshToken: request.RefreshToken,
|
||||
}); err != nil {
|
||||
h.handleKeycloakError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// REFRESH USER TOKEN
|
||||
// ------------------------------
|
||||
|
||||
func (h *handler) refreshTokenHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "refreshTokenHandler"
|
||||
|
||||
var request rmodel.RefreshTokenRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while decoding request body: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := h.authManager.GetNewAccessToken(r.Context(), auth.GetNewAccessTokenRequest{
|
||||
RefreshToken: request.RefreshToken,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleKeycloakError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := json.NewEncoder(w).Encode(rmodel.RefreshTokenResponse{
|
||||
AccessToken: resp.AccessToken,
|
||||
RefreshToken: resp.RefreshToken,
|
||||
}); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error while encoding response: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) confirmEmailPageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "confirmEmailPageHandler"
|
||||
|
||||
if r.Method != http.MethodGet {
|
||||
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
uid := r.URL.Query().Get("uid")
|
||||
token := r.URL.Query().Get("token")
|
||||
|
||||
if uid == "" || token == "" {
|
||||
http.Error(w, "Bad Request: отсутствует uid или token", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
scheme := "http"
|
||||
|
||||
if protocol := r.Header.Get("X-Forwarded-Proto"); protocol != "" {
|
||||
scheme = protocol
|
||||
} else if h.env == "production" || h.env == "development" {
|
||||
scheme = "https"
|
||||
}
|
||||
|
||||
// Формируем URL для PATCH-запроса
|
||||
verificationLink := fmt.Sprintf("%s://%s/api/v1/verify_email?uid=%s&token=%s",
|
||||
scheme,
|
||||
r.Host,
|
||||
url.QueryEscape(uid),
|
||||
url.QueryEscape(token),
|
||||
)
|
||||
|
||||
tmpl, err := template.New("confirm").Parse(constants.EmailConfirmationPage)
|
||||
if err != nil {
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
|
||||
if err := tmpl.Execute(w, struct {
|
||||
VerificationURL string
|
||||
}{
|
||||
VerificationURL: verificationLink,
|
||||
}); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error while executing confirm email page template",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// RESET PASSWORD
|
||||
// ------------------------------
|
||||
|
||||
func (h *handler) forgotPasswordHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "forgotPasswordHandler"
|
||||
|
||||
var request rmodel.ForgotPasswordRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while decoding request body: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
createOTPResp, err := h.authInfraService.CreatePasswordResetOTP(r.Context(), &authinfra.PasswordResetOTPCreateRequest{
|
||||
Email: request.Email,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleAuthInfraError(w, err, handlerName)
|
||||
return
|
||||
}
|
||||
|
||||
message, err := proto.Marshal(¬ification.SendEmailRequest{
|
||||
To: []string{request.Email},
|
||||
Subject: constants.ForgotPasswordNotificationMessageSubject,
|
||||
ContentType: constants.TextNotificationContentType,
|
||||
Body: fmt.Appendf(nil,
|
||||
constants.ForgotPasswordNotificationText,
|
||||
createOTPResp.OTP,
|
||||
),
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error while marshaling forgot password notification message",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err := broker.SendNotification(
|
||||
broker.NotificationQueue,
|
||||
constants.EmailNotificationMessageType,
|
||||
message,
|
||||
h.logger,
|
||||
); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error while sending forgot password notification",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
}
|
||||
|
||||
func (h *handler) validateOTPHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "validateOTPHandler"
|
||||
|
||||
query := r.URL.Query()
|
||||
|
||||
email := query.Get("email")
|
||||
if email == "" {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Debug("email is required, but missing",
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
otp := query.Get("otp")
|
||||
if otp == "" {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Debug("OTP is required, but missing",
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
checkOTPResp, err := h.authInfraService.ValidatePasswordResetOTP(r.Context(), &authinfra.ValidatePasswordResetOTPRequest{
|
||||
Email: email,
|
||||
OTP: otp,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleAuthInfraError(w, err, handlerName)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(rmodel.ValidateOTPResponse{
|
||||
Token: checkOTPResp.Token,
|
||||
}); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) resetPasswordHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "resetPasswordHandler"
|
||||
|
||||
var request rmodel.ResetPasswordRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error decoding request body: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := h.authInfraService.ValidatePasswordResetToken(r.Context(), &authinfra.ValidatePasswordResetTokenRequest{
|
||||
Email: request.Email,
|
||||
Token: request.Token,
|
||||
}); err != nil {
|
||||
h.handleAuthInfraError(w, err, handlerName)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.authManager.ResetPassword(r.Context(), auth.ResetPasswordRequest{
|
||||
Email: request.Email,
|
||||
NewPassword: request.Password,
|
||||
}); err != nil {
|
||||
h.handleKeycloakError(w, err)
|
||||
h.logger.Error("error resetting password",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
769
internal/http/balance.go
Normal file
@@ -0,0 +1,769 @@
|
||||
package http_router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
|
||||
rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (h *handler) getBalanceAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getBalanceAgentHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
)
|
||||
|
||||
result, err := h.agentService.GetBalance(r.Context(), &rmodel.BalanceGetRequest{
|
||||
OwnerId: agentId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error getting balance info",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getTransactionListAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getTransactionListAgentHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
)
|
||||
|
||||
request, err := new(rmodel.TransactionListGetRequest).FromQuery(r.URL.Query())
|
||||
if err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error parsing request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
request.OwnerId = agentId
|
||||
|
||||
result, err := h.agentService.GetTransactionList(r.Context(), request)
|
||||
if err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error getting transactions",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createTransactionAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "createTransactionAgentHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
)
|
||||
|
||||
var request rmodel.TransactionCreateRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
defer func(body io.ReadCloser) {
|
||||
if err := body.Close(); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error closing body",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}(r.Body)
|
||||
|
||||
request.OwnerId = agentId
|
||||
|
||||
result, err := h.agentService.CreateTransaction(r.Context(), &request)
|
||||
if err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error creating transaction",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: fix feed event
|
||||
// go h.createTransactionFeedEvent(
|
||||
// context.Background(),
|
||||
// agentId,
|
||||
// true,
|
||||
// request.Amount,
|
||||
// request.Currency,
|
||||
// request.BankAccountId,
|
||||
// handlerName,
|
||||
// )
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getBankAccountListAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getBankAccountListAgentHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
)
|
||||
|
||||
result, err := h.agentService.GetBankAccountList(r.Context(), &rmodel.BankAccountListGetRequest{
|
||||
OwnerId: agentId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error getting bank accounts",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createBankAccountAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "createBankAccountAgentHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
)
|
||||
|
||||
var request rmodel.BankAccountCreateRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
defer func(body io.ReadCloser) {
|
||||
if err := body.Close(); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error closing body",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}(r.Body)
|
||||
|
||||
request.OwnerId = agentId
|
||||
|
||||
result, err := h.agentService.CreateBankAccount(r.Context(), &request)
|
||||
if err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error creating bank account",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME: possible nil dereference
|
||||
// h.createCreateBankAccountFeedEvent(r.Context(), agentId, true, resp, *request.BankName, handlerName)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) updateBankAccountAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "updateBankAccountAgentHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
bankAccountId = vars["bank_account_id"]
|
||||
)
|
||||
|
||||
var request rmodel.BankAccountUpdateRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
defer func(body io.ReadCloser) {
|
||||
if err := body.Close(); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error closing body",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}(r.Body)
|
||||
|
||||
request.Id = bankAccountId
|
||||
request.OwnerId = agentId
|
||||
|
||||
if _, err := h.agentService.UpdateBankAccount(r.Context(), &request); err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error editing bank account",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
go h.createEditBankAccountFeedEvent(
|
||||
context.Background(),
|
||||
agentId,
|
||||
true,
|
||||
bankAccountId,
|
||||
handlerName,
|
||||
)
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// TODO: test when implemented
|
||||
func (h *handler) deleteBankAccountAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "deleteBankAccountAgentHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
bankAccountId = vars["bank_account_id"]
|
||||
)
|
||||
|
||||
result, err := h.agentService.DeleteBankAccount(r.Context(), &rmodel.BankAccountDeleteRequest{
|
||||
Id: bankAccountId,
|
||||
OwnerId: agentId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error deleting bank account",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := h.feed.CancelEvent(context.Background(), bankAccountId, "Банковский счёт удален"); err != nil {
|
||||
h.logger.Error("error cancelling event: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}()
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getBalanceDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getBalanceDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
distId = vars["distributor_id"]
|
||||
)
|
||||
|
||||
result, err := h.distributorService.GetBalance(r.Context(), &rmodel.BalanceGetRequest{
|
||||
OwnerId: distId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error getting balance",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getCompanyBalanceDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getCompanyBalanceDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
companyId = vars["company_id"]
|
||||
)
|
||||
|
||||
result, err := h.distributorService.GetBalance(r.Context(), &rmodel.BalanceGetRequest{
|
||||
OwnerId: companyId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error getting balance",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getTransactionListDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getTransactionListDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
distId = vars["distributor_id"]
|
||||
)
|
||||
|
||||
request, err := new(rmodel.TransactionListGetRequest).FromQuery(r.URL.Query())
|
||||
if err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error parsing request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
request.OwnerId = distId
|
||||
|
||||
result, err := h.distributorService.GetTransactionList(r.Context(), request)
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error getting transactions",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getCompanyTransactionListDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getCompanyTransactionListDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
companyId = vars["company_id"]
|
||||
)
|
||||
|
||||
request, err := new(rmodel.TransactionListGetRequest).FromQuery(r.URL.Query())
|
||||
if err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error parsing request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
request.OwnerId = companyId
|
||||
|
||||
result, err := h.distributorService.GetTransactionList(r.Context(), request)
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error getting transactions",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createTransactionDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "createTransactionDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
distId = vars["distributor_id"]
|
||||
)
|
||||
|
||||
var request rmodel.TransactionCreateRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
defer func(body io.ReadCloser) {
|
||||
if err := body.Close(); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error closing body",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}(r.Body)
|
||||
|
||||
request.OwnerId = distId
|
||||
|
||||
result, err := h.distributorService.CreateTransaction(r.Context(), &request)
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error creating transaction",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: fix feed event
|
||||
// go h.createTransactionFeedEvent(
|
||||
// context.Background(),
|
||||
// distId,
|
||||
// false,
|
||||
// request.Amount,
|
||||
// request.Currency,
|
||||
// request.BankAccountId,
|
||||
// handlerName,
|
||||
// )
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getBankAccountListDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getBankAccountListDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
distId = vars["distributor_id"]
|
||||
)
|
||||
|
||||
result, err := h.distributorService.GetBankAccountList(r.Context(), &rmodel.BankAccountListGetRequest{
|
||||
OwnerId: distId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error getting bank accounts",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getCompanyBankAccountListDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getCompanyBankAccountListDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
companyId = vars["company_id"]
|
||||
)
|
||||
|
||||
result, err := h.distributorService.GetBankAccountList(r.Context(), &rmodel.BankAccountListGetRequest{
|
||||
OwnerId: companyId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error getting bank accounts",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createBankAccountDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "createBankAccountDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
companyId = vars["company_id"]
|
||||
)
|
||||
|
||||
var request rmodel.BankAccountCreateRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
defer func(body io.ReadCloser) {
|
||||
if err := body.Close(); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error closing body",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}(r.Body)
|
||||
|
||||
request.OwnerId = companyId
|
||||
|
||||
result, err := h.distributorService.CreateBankAccount(r.Context(), &request)
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error creating bank account",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME: possible nil dereference
|
||||
// go h.createCreateBankAccountFeedEvent(
|
||||
// context.Background(),
|
||||
// distId,
|
||||
// false,
|
||||
// resp,
|
||||
// *request.BankName,
|
||||
// handlerName,
|
||||
// )
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) updateBankAccountDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "updateBankAccountDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
distId = vars["distributor_id"]
|
||||
bankAccountId = vars["bank_account_id"]
|
||||
)
|
||||
|
||||
var request rmodel.BankAccountUpdateRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
defer func(body io.ReadCloser) {
|
||||
if err := body.Close(); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error closing body",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}(r.Body)
|
||||
|
||||
request.OwnerId = distId
|
||||
request.Id = bankAccountId
|
||||
|
||||
result, err := h.distributorService.UpdateBankAccount(r.Context(), &request)
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error editing bank account",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
go h.createEditBankAccountFeedEvent(
|
||||
context.Background(),
|
||||
distId,
|
||||
true,
|
||||
bankAccountId,
|
||||
handlerName,
|
||||
)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) deleteBankAccountDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "deleteBankAccountDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
distId = vars["distributor_id"]
|
||||
bankAccountId = vars["bank_account_id"]
|
||||
)
|
||||
|
||||
result, err := h.distributorService.DeleteBankAccount(r.Context(), &rmodel.BankAccountDeleteRequest{
|
||||
Id: bankAccountId,
|
||||
OwnerId: distId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error deleting bank account",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := h.feed.CancelEvent(context.Background(), bankAccountId, "Банковский счёт удален"); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error while cancelling event: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}()
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
27
internal/http/build_info.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package http_router
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (h *handler) getBuildInfoHandler(w http.ResponseWriter, _ *http.Request) {
|
||||
response := struct {
|
||||
Version string `json:"version"`
|
||||
Commit string `json:"commit"`
|
||||
Date string `json:"date"`
|
||||
}{
|
||||
Version: h.buildConfig.Version,
|
||||
Commit: h.buildConfig.Commit,
|
||||
Date: h.buildConfig.Date,
|
||||
}
|
||||
|
||||
responseJSON, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write(responseJSON)
|
||||
}
|
||||
182
internal/http/client.go
Normal file
@@ -0,0 +1,182 @@
|
||||
package http_router
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/cache"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database"
|
||||
dberrors "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/database/errors"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/feed"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/integration"
|
||||
objectStorage "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/object_storage"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/services/agent"
|
||||
authinfra "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/services/auth_infrastructure"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/services/distributor"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/auth"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/auth/keycloak"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/config"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
|
||||
filemanager "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/file_manager"
|
||||
urlShortener "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/url_shortener"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
env string
|
||||
logger *slog.Logger
|
||||
urlShortener urlShortener.Shortener
|
||||
authManager auth.Manager
|
||||
authInfraService authinfra.AuthInfrastructureService
|
||||
fileManager filemanager.UserFileManager
|
||||
dbClient database.Client
|
||||
agentService agent.AgentService
|
||||
distributorService distributor.DistributorService
|
||||
cacheClient cache.Client
|
||||
objectStorageClient objectStorage.Client
|
||||
jwtManager keycloak.TokenManager
|
||||
tempFileManager *TempFileManager
|
||||
emailVerificationServiceAPIKey string
|
||||
feed *feed.Handler
|
||||
integrationClient integration.Client
|
||||
buildConfig config.BuildInfo
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
env string
|
||||
logger *slog.Logger
|
||||
secretConfig *config.SecretConfig
|
||||
authManager auth.Manager
|
||||
authInfraService authinfra.AuthInfrastructureService
|
||||
fileManager filemanager.UserFileManager
|
||||
dbClient database.Client
|
||||
agentService agent.AgentService
|
||||
distributorService distributor.DistributorService
|
||||
emailVerificationServiceAPIKey string
|
||||
cacheClient cache.Client
|
||||
objectStorageClient objectStorage.Client
|
||||
feed *feed.Handler
|
||||
integrationClient integration.Client
|
||||
buildConfig config.BuildInfo
|
||||
}
|
||||
|
||||
func newHandler(c *Config) *handler {
|
||||
tempManager, err := NewTempFileManager("")
|
||||
if err != nil {
|
||||
c.logger.Error("failed to create temp file manager", slog.String("error", err.Error()))
|
||||
return nil
|
||||
}
|
||||
|
||||
return &handler{
|
||||
env: c.env,
|
||||
logger: c.logger,
|
||||
urlShortener: &urlShortener.LinkEncryption{Key: c.secretConfig.Key},
|
||||
authManager: c.authManager,
|
||||
authInfraService: c.authInfraService,
|
||||
fileManager: c.fileManager,
|
||||
dbClient: c.dbClient,
|
||||
agentService: c.agentService,
|
||||
distributorService: c.distributorService,
|
||||
emailVerificationServiceAPIKey: c.emailVerificationServiceAPIKey,
|
||||
cacheClient: c.cacheClient,
|
||||
objectStorageClient: c.objectStorageClient,
|
||||
jwtManager: keycloak.NewJWTManager(),
|
||||
tempFileManager: tempManager,
|
||||
feed: c.feed,
|
||||
integrationClient: c.integrationClient,
|
||||
buildConfig: c.buildConfig,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) handleKeycloakError(w http.ResponseWriter, err error) {
|
||||
switch {
|
||||
case errors.Is(err, keycloak.ErrUnknownUserType):
|
||||
http.Error(w, keycloak.ErrUnknownUserType.Error(), http.StatusBadRequest)
|
||||
case errors.Is(err, keycloak.ErrInvalidToken):
|
||||
http.Error(w, keycloak.ErrInvalidToken.Error(), http.StatusUnauthorized)
|
||||
case errors.Is(err, keycloak.ErrRealmClientUnauthorized):
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
case errors.Is(err, keycloak.ErrRealmClientNotFound):
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
case errors.Is(err, keycloak.ErrInternal):
|
||||
http.Error(w, keycloak.ErrInternal.Error(), http.StatusInternalServerError)
|
||||
case errors.Is(err, keycloak.ErrAlreadyExists):
|
||||
http.Error(w, keycloak.ErrAlreadyExists.Error(), http.StatusBadRequest)
|
||||
case errors.Is(err, keycloak.ErrBadRequest):
|
||||
http.Error(w, keycloak.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
case errors.Is(err, keycloak.ErrNotFound):
|
||||
http.Error(w, keycloak.ErrNotFound.Error(), http.StatusNotFound)
|
||||
default:
|
||||
h.logger.Error("Unhandled keycloak error", slog.String("error", err.Error()))
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) handleAuthInfraError(w http.ResponseWriter, err error, handlerName string) {
|
||||
switch {
|
||||
case errors.Is(err, authinfra.ErrBadRequest):
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
case errors.Is(err, authinfra.ErrUnauthorized):
|
||||
http.Error(w, constants.ErrUnauthorized.Error(), http.StatusUnauthorized)
|
||||
case errors.Is(err, authinfra.ErrNotFound):
|
||||
http.Error(w, constants.ErrUnauthorized.Error(), http.StatusUnauthorized)
|
||||
case errors.Is(err, authinfra.ErrInternal):
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("auth infrastructure error",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
default:
|
||||
h.logger.Error("Unhandled auth infrastructure error", slog.String("error", err.Error()))
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) handleDBError(w http.ResponseWriter, err error) {
|
||||
switch {
|
||||
case errors.Is(err, dberrors.ErrBadRequest):
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
case errors.Is(err, dberrors.ErrForbidden):
|
||||
http.Error(w, constants.ErrForbidden.Error(), http.StatusForbidden)
|
||||
case errors.Is(err, dberrors.ErrNotFound):
|
||||
http.Error(w, constants.ErrNotFound.Error(), http.StatusNotFound)
|
||||
case errors.Is(err, dberrors.ErrInternal):
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
default:
|
||||
h.logger.Error("Unhandled database error", slog.String("error", err.Error()))
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) handleAgentError(w http.ResponseWriter, err error) {
|
||||
switch {
|
||||
case errors.Is(err, agent.ErrBadRequest):
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
case errors.Is(err, agent.ErrForbidden):
|
||||
http.Error(w, constants.ErrForbidden.Error(), http.StatusForbidden)
|
||||
case errors.Is(err, agent.ErrNotFound):
|
||||
http.Error(w, constants.ErrNotFound.Error(), http.StatusNotFound)
|
||||
case errors.Is(err, agent.ErrInternal):
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
default:
|
||||
h.logger.Error("Unhandled agent error", slog.String("error", err.Error()))
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) handleDistributorError(w http.ResponseWriter, err error) {
|
||||
switch {
|
||||
case errors.Is(err, distributor.ErrBadRequest):
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
case errors.Is(err, distributor.ErrForbidden):
|
||||
http.Error(w, constants.ErrForbidden.Error(), http.StatusForbidden)
|
||||
case errors.Is(err, distributor.ErrNotFound):
|
||||
http.Error(w, constants.ErrNotFound.Error(), http.StatusNotFound)
|
||||
case errors.Is(err, distributor.ErrInternal):
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
default:
|
||||
h.logger.Error("Unhandled distributor error", slog.String("error", err.Error()))
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
168
internal/http/company_agent.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package http_router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model"
|
||||
)
|
||||
|
||||
func (h *handler) getCompanyListAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getCompanyListAgentHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
)
|
||||
|
||||
result, err := h.agentService.GetCompanyList(r.Context(), &rmodel.CompanyListGetRequest{
|
||||
Id: agentId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error getting company list",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getCompanyByIdAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getCompanyByIdAgentHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
companyId = vars["company_id"]
|
||||
)
|
||||
|
||||
result, err := h.agentService.GetCompanyInfo(r.Context(), &rmodel.CompanyByIdGetRequest{
|
||||
UserId: agentId,
|
||||
CompanyId: companyId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error getting company info",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: foreign key violation review
|
||||
func (h *handler) createCompanyAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "createAgentCompanyHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
)
|
||||
|
||||
var request rmodel.CompanyCreateRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
request.OwnerId = agentId
|
||||
|
||||
result, err := h.agentService.CreateCompany(r.Context(), &request)
|
||||
if err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error creating company",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
// go h.createCreateCompanyFeedEvent(r.Context(), agentId, true, resp, handlerName)
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) updateCompanyAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "updateCompanyAgentHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
agentId = vars["agent_id"]
|
||||
companyId = vars["company_id"]
|
||||
)
|
||||
|
||||
var request rmodel.CompanyUpdateRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
request.Id = companyId
|
||||
|
||||
if _, err := h.agentService.UpdateCompanyInfo(r.Context(), &request); err != nil {
|
||||
h.handleAgentError(w, err)
|
||||
h.logger.Error("error updating company info",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
go h.createEditCompanyFeedEvent(
|
||||
context.Background(),
|
||||
agentId,
|
||||
true,
|
||||
companyId,
|
||||
handlerName,
|
||||
)
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
199
internal/http/company_distributor.go
Normal file
@@ -0,0 +1,199 @@
|
||||
package http_router
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
|
||||
rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (h *handler) getCompanyListDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getCompanyListDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
distId = vars["distributor_id"]
|
||||
)
|
||||
|
||||
result, err := h.distributorService.GetCompanyList(r.Context(), &rmodel.CompanyListGetRequest{
|
||||
Id: distId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error getting company list",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) getCompanyByIdDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "getCompanyByIdDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
distId = vars["distributor_id"]
|
||||
companyId = vars["company_id"]
|
||||
)
|
||||
|
||||
result, err := h.distributorService.GetCompanyInfoById(r.Context(), &rmodel.CompanyByIdGetRequest{
|
||||
UserId: distId,
|
||||
CompanyId: companyId,
|
||||
})
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error getting company list",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createCompanyDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "createCompanyDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
distId = vars["distributor_id"]
|
||||
)
|
||||
|
||||
var request rmodel.CompanyCreateRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
request.OwnerId = distId
|
||||
|
||||
result, err := h.distributorService.CreateCompany(r.Context(), &request)
|
||||
if err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error creating company",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// h.createCreateCompanyFeedEvent(r.Context(), distId, false, resp, handlerName)
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if err := json.NewEncoder(w).Encode(result); err != nil {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error encoding response",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) updateCompanyDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "updateCompanyDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
companyId = vars["company_id"]
|
||||
)
|
||||
|
||||
var request rmodel.CompanyUpdateRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
request.Id = companyId
|
||||
|
||||
if _, err := h.distributorService.UpdateCompanyInfo(r.Context(), &request); err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error updating company info",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// BUG: holds request for infinite time
|
||||
// h.createEditCompanyFeedEvent(r.Context(), distId, false, comId, handlerName)
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func (h *handler) addCompanyMemberDistributorHandler(w http.ResponseWriter, r *http.Request) {
|
||||
const handlerName = "addCompanyMemberDistributorHandler"
|
||||
|
||||
var (
|
||||
vars = mux.Vars(r)
|
||||
companyId = vars["company_id"]
|
||||
)
|
||||
|
||||
var request rmodel.AddDistributorCompanyMemberRequest
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
||||
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("error while unmarshalling request: ",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
request.CompanyId = companyId
|
||||
|
||||
if _, err := h.distributorService.AddEmployee(r.Context(), &request); err != nil {
|
||||
h.handleDistributorError(w, err)
|
||||
h.logger.Error("error adding new staff member",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// h.createAddNewStaffMemberFeedEvent(r.Context(), distId, true, *req.NewStaffMember, companyId, handlerName)
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
75
internal/http/errors.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package http_router
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// =============== CUSTOM LOGO ERRORS ===============
|
||||
var (
|
||||
ErrEmptyFile = errors.New("file is empty")
|
||||
ErrMultipartParse = errors.New("failed to parse multipart form")
|
||||
ErrFileNotFound = errors.New("failed to get file from form")
|
||||
ErrTempFileCreate = errors.New("failed to create temporary file")
|
||||
ErrFileOperation = errors.New("file operation failed")
|
||||
)
|
||||
|
||||
// InvalidImageTypeError представляет ошибку неверного типа изображения
|
||||
type InvalidImageTypeError struct {
|
||||
ContentType string
|
||||
}
|
||||
|
||||
func (e *InvalidImageTypeError) Error() string {
|
||||
return fmt.Sprintf("invalid image type %s: only png, jpg, and webp are allowed", e.ContentType)
|
||||
}
|
||||
|
||||
// FileTooLargeError представляет ошибку превышения размера файла
|
||||
type FileTooLargeError struct {
|
||||
Size int64
|
||||
MaxSize int64
|
||||
}
|
||||
|
||||
func (e *FileTooLargeError) Error() string {
|
||||
return fmt.Sprintf("file too large: %d bytes, max %d bytes allowed", e.Size, e.MaxSize)
|
||||
}
|
||||
|
||||
// =============== ERROR HANDLERS ===============
|
||||
|
||||
// handleAccessError обрабатывает ошибки прав или токенов
|
||||
func (h *handler) handleAccessError(w http.ResponseWriter, err error, handlerName string) {
|
||||
if errors.Is(err, constants.ErrUnauthorized) {
|
||||
http.Error(w, constants.ErrUnauthorized.Error(), http.StatusUnauthorized)
|
||||
} else if errors.Is(err, constants.ErrForbidden) {
|
||||
http.Error(w, constants.ErrForbidden.Error(), http.StatusForbidden)
|
||||
} else {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("some permission or authorization error",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}
|
||||
|
||||
// handleUploadError обрабатывает ошибки логотипов
|
||||
func (h *handler) handleUploadError(w http.ResponseWriter, err error, handlerName string) {
|
||||
var invalidTypeErr *InvalidImageTypeError
|
||||
|
||||
var fileTooLargeErr *FileTooLargeError
|
||||
|
||||
// Проверяем типизированные ошибки
|
||||
if errors.As(err, &invalidTypeErr) || errors.As(err, &fileTooLargeErr) ||
|
||||
errors.Is(err, ErrEmptyFile) || errors.Is(err, ErrMultipartParse) ||
|
||||
errors.Is(err, ErrFileNotFound) {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
h.logger.Error("client error uploading logo",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
} else {
|
||||
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
|
||||
h.logger.Error("error processing logo upload",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName))
|
||||
}
|
||||
}
|
||||
474
internal/http/feed.go
Normal file
@@ -0,0 +1,474 @@
|
||||
package http_router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/feed"
|
||||
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/types"
|
||||
pbfAgent "github.com/AlexOreL-272/ProtoMolva/go/gen/agent"
|
||||
pbfDistr "github.com/AlexOreL-272/ProtoMolva/go/gen/distributor"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
//nolint:unused // TODO: review feed handlers
|
||||
func (h *handler) createCreateCompanyFeedEvent(ctx context.Context, uid string, isAgent bool, resp []byte, handlerName string) {
|
||||
var (
|
||||
jsonResp interface{}
|
||||
companyID string
|
||||
companyName string
|
||||
)
|
||||
|
||||
if isAgent {
|
||||
jsonResp = new(pbfAgent.SetCompanyDataResponse)
|
||||
} else {
|
||||
jsonResp = new(pbfDistr.SetCompanyDataResponse)
|
||||
}
|
||||
|
||||
ownerType := feed.RoleDistributor
|
||||
if isAgent {
|
||||
ownerType = feed.RoleAgent
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(resp, jsonResp); err != nil {
|
||||
h.logger.Error(fmt.Sprintf("failed to unmarshal %s SetCompanyDataResponse", ownerType),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
switch resp := jsonResp.(type) {
|
||||
case *pbfAgent.SetCompanyDataResponse:
|
||||
company := resp.GetCompany()
|
||||
companyID = company.GetCompanyId()
|
||||
companyName = company.GetName()
|
||||
|
||||
case *pbfDistr.SetCompanyDataResponse:
|
||||
company := resp.GetCompany()
|
||||
companyID = company.GetCompanyId()
|
||||
companyName = company.GetName()
|
||||
|
||||
default:
|
||||
h.logger.Error("unexpected response type",
|
||||
slog.String("handler", handlerName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
event := feed.Event{
|
||||
OwnerId: uid,
|
||||
OwnerType: ownerType,
|
||||
EventType: feed.EventCompanyCreated,
|
||||
Message: fmt.Sprintf("Компания %s создана", companyName),
|
||||
Visibility: feed.VisibilityCompanyWide,
|
||||
CompanyID: &companyID,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: companyID,
|
||||
AttachmentType: feed.AttachmentTypeCompany,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("uid", uid),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("company_id", companyID),
|
||||
slog.String("company_id", companyID),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:unused // TODO: review feed handlers
|
||||
func (h *handler) createAddNewStaffMemberFeedEvent(ctx context.Context, uid string, isAgent bool, newStaffMember, companyId, handlerName string) {
|
||||
ownerType := feed.RoleDistributor
|
||||
|
||||
if isAgent {
|
||||
ownerType = feed.RoleAgent
|
||||
}
|
||||
|
||||
event := feed.Event{
|
||||
OwnerId: uid,
|
||||
OwnerType: ownerType,
|
||||
EventType: feed.EventNewCompanyMember,
|
||||
Message: "Новый сотрудник добавлен в компанию",
|
||||
Visibility: feed.VisibilityCompanyWide,
|
||||
CompanyID: &companyId,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: newStaffMember,
|
||||
AttachmentType: feed.AttachmentTypeProfile,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("uid", uid),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("company_id", companyId),
|
||||
slog.String("new_staff_member", newStaffMember),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:unused // TODO: review feed handlers
|
||||
func (h *handler) createSetSubmissionStatusFeedEvent(ctx context.Context, distributorId, submissionId string, submissionStatus types.Status, handlerName string) {
|
||||
var message string
|
||||
|
||||
switch submissionStatus {
|
||||
case types.StatusAccepted:
|
||||
message = "Отклик на вакансию принят"
|
||||
case types.StatusDeclined:
|
||||
message = "Отклик на вакансию отклонен"
|
||||
case types.StatusSuspended:
|
||||
message = "Отклик на вакансию отложен"
|
||||
default:
|
||||
message = "Статус отклика на вакансию был изменен"
|
||||
}
|
||||
|
||||
companyIds, err := h.feed.GetCompanyIdByUidTmp(ctx, distributorId)
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get company Id",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("distributor_id", distributorId))
|
||||
}
|
||||
|
||||
agentId, err := h.feed.GetAgentIdBySubmissionId(ctx, submissionId)
|
||||
if err != nil {
|
||||
//я хз стоит ли отдельно как-то обрабатывать ErrorNotFound(вроде как нет)
|
||||
h.logger.Error("failed to get agent Id",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("submission_id", submissionId))
|
||||
}
|
||||
|
||||
for _, companyId := range companyIds {
|
||||
event := feed.Event{
|
||||
OwnerId: distributorId,
|
||||
OwnerType: feed.RoleDistributor,
|
||||
EventType: feed.EventSubmissionStatusChanged,
|
||||
Message: message,
|
||||
Visibility: feed.VisibilityCompanyWide,
|
||||
CompanyID: &companyId,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: submissionId,
|
||||
AttachmentType: feed.AttachmentTypeCV,
|
||||
AdditionalReceiver: agentId,
|
||||
CustomData: submissionStatus.String(),
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("distributor_id", distributorId),
|
||||
slog.String("agent_id", agentId),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("submission_id", submissionId),
|
||||
slog.String("company_id", companyId),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:unused // TODO: review feed handlers
|
||||
func (h *handler) createTransactionFeedEvent(ctx context.Context, uid string, isAgent bool, amount int64, currency, bankAccountId, handlerName string) {
|
||||
var message string
|
||||
|
||||
if amount > 0 {
|
||||
message = fmt.Sprintf("Вы получили %.2f %s", float64(amount)/100, currency)
|
||||
} else {
|
||||
message = fmt.Sprintf("С вашего аккаунта выведено %.2f %s", float64(-amount)/100, currency)
|
||||
}
|
||||
|
||||
ownerType := feed.RoleDistributor
|
||||
|
||||
if isAgent {
|
||||
ownerType = feed.RoleAgent
|
||||
}
|
||||
|
||||
event := feed.Event{
|
||||
OwnerId: uid,
|
||||
OwnerType: ownerType,
|
||||
EventType: feed.EventTransactionCreated,
|
||||
Message: message,
|
||||
Visibility: feed.VisibilityPrivate,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: bankAccountId,
|
||||
AttachmentType: feed.AttachmentTypeBankAccount,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("uid", uid),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("bank_account_id", bankAccountId))
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:unused // TODO: review feed handlers
|
||||
func (h *handler) createCreateBankAccountFeedEvent(ctx context.Context, uid string, isAgent bool, resp []byte, bankName, handlerName string) {
|
||||
var msg proto.Message
|
||||
|
||||
var ownerType feed.UserRole
|
||||
|
||||
if isAgent {
|
||||
msg = &pbfAgent.CreateBankAccountResponse{}
|
||||
ownerType = feed.RoleAgent
|
||||
} else {
|
||||
msg = &pbfDistr.CreateBankAccountResponse{}
|
||||
ownerType = feed.RoleDistributor
|
||||
}
|
||||
|
||||
if err := protojson.Unmarshal(resp, msg); err != nil {
|
||||
h.logger.Error(fmt.Sprintf("failed to unmarshal %s CreateBankAccountResponse", ownerType),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var bankAccountId string
|
||||
switch v := msg.(type) {
|
||||
case *pbfAgent.CreateBankAccountResponse:
|
||||
bankAccountId = v.GetBankAccountId()
|
||||
case *pbfDistr.CreateBankAccountResponse:
|
||||
bankAccountId = v.GetBankAccountId()
|
||||
default:
|
||||
h.logger.Error("unexpected response type",
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
event := feed.Event{
|
||||
OwnerId: uid,
|
||||
OwnerType: ownerType,
|
||||
EventType: feed.EventBankAccountCreated,
|
||||
Message: fmt.Sprintf("Банковский счёт %s создан", bankName),
|
||||
Visibility: feed.VisibilityPrivate,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: bankAccountId,
|
||||
AttachmentType: feed.AttachmentTypeBankAccount,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("uid", uid),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("bank_account_id", bankAccountId),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createEditBankAccountFeedEvent(ctx context.Context, uid string, isAgent bool, bankAccountID, handlerName string) {
|
||||
ownerType := feed.RoleDistributor
|
||||
|
||||
if isAgent {
|
||||
ownerType = feed.RoleAgent
|
||||
}
|
||||
|
||||
event := feed.Event{
|
||||
OwnerId: uid,
|
||||
OwnerType: ownerType,
|
||||
EventType: feed.EventBankAccountChanged,
|
||||
Message: "Банковский счёт обновлён",
|
||||
Visibility: feed.VisibilityPrivate,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: bankAccountID,
|
||||
AttachmentType: feed.AttachmentTypeBankAccount,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("uid", uid),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("bank_account_id", bankAccountID))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createEditCompanyFeedEvent(ctx context.Context, uid string, isAgent bool, companyID, handlerName string) {
|
||||
ownerType := feed.RoleDistributor
|
||||
|
||||
if isAgent {
|
||||
ownerType = feed.RoleAgent
|
||||
}
|
||||
|
||||
event := feed.Event{
|
||||
OwnerId: uid,
|
||||
OwnerType: ownerType,
|
||||
EventType: feed.EventCompanyChanged,
|
||||
Message: "Данные компании обновлены",
|
||||
Visibility: feed.VisibilityCompanyWide,
|
||||
CompanyID: &companyID,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: companyID,
|
||||
AttachmentType: feed.AttachmentTypeCompany,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("uid", uid),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("company_id", companyID))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createSetProfileEvent(ctx context.Context, uid string, isAgent bool, handlerName string) {
|
||||
ownerType := feed.RoleDistributor
|
||||
|
||||
if isAgent {
|
||||
ownerType = feed.RoleAgent
|
||||
}
|
||||
|
||||
event := feed.Event{
|
||||
OwnerId: uid,
|
||||
OwnerType: ownerType,
|
||||
EventType: feed.EventProfileChanged,
|
||||
Message: "Ваши данные профиля обновлены",
|
||||
Visibility: feed.VisibilityPrivate,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: uid,
|
||||
AttachmentType: feed.AttachmentTypeProfile,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("uid", uid),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createSetDistributorVacancyEvent(ctx context.Context, distributorId, vacancyId, vacancyName, handlerName string) {
|
||||
event := feed.Event{
|
||||
OwnerId: distributorId,
|
||||
OwnerType: feed.RoleDistributor,
|
||||
EventType: feed.EventVacancyCreated,
|
||||
Message: fmt.Sprintf("Вакансия %s была создана", vacancyName),
|
||||
Visibility: feed.VisibilityPublic,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: vacancyId,
|
||||
AttachmentType: feed.AttachmentTypeVacancy,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("distributor_id", distributorId),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("vacancy_id", vacancyId),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createEditDistributorVacancyEvent(ctx context.Context, distributorId, vacancyId, handlerName string) {
|
||||
event := feed.Event{
|
||||
OwnerId: distributorId,
|
||||
OwnerType: feed.RoleDistributor,
|
||||
EventType: feed.EventVacancyChanged,
|
||||
Message: "Вакансия была изменена",
|
||||
Visibility: feed.VisibilityPublic,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: vacancyId,
|
||||
AttachmentType: feed.AttachmentTypeVacancy,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("distributor_id", distributorId),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("vacancy_id", vacancyId))
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createSendVacancyToModerationEvent(ctx context.Context, distributorId, vacancyId, handlerName string) {
|
||||
companyIds, err := h.feed.GetCompanyIdByUidTmp(ctx, distributorId)
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get company Id",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("distributor_id", distributorId))
|
||||
}
|
||||
|
||||
for _, companyId := range companyIds {
|
||||
event := feed.Event{
|
||||
OwnerId: distributorId,
|
||||
OwnerType: feed.RoleDistributor,
|
||||
EventType: feed.EventVacancyModerationSent,
|
||||
Message: "Вакансия была отправлена на модерацию",
|
||||
Visibility: feed.VisibilityCompanyWide,
|
||||
CompanyID: &companyId,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: vacancyId,
|
||||
AttachmentType: feed.AttachmentTypeVacancy,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("distributor_id", distributorId),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("vacancy_id", vacancyId),
|
||||
slog.String("company_id", companyId),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) createPostAnketaEvent(ctx context.Context, agentID, submissionId, handlerName string) {
|
||||
companyIds, err := h.feed.GetCompanyIdByUidTmp(ctx, agentID)
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get company Id",
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("agent_id", agentID))
|
||||
}
|
||||
|
||||
for _, companyId := range companyIds {
|
||||
event := feed.Event{
|
||||
OwnerId: agentID,
|
||||
OwnerType: feed.RoleAgent,
|
||||
EventType: feed.EventPostAnketa,
|
||||
Message: "Анкета была заполнена",
|
||||
Visibility: feed.VisibilityPrivate,
|
||||
CompanyID: &companyId,
|
||||
Payload: feed.EventPayload{
|
||||
AttachmentId: submissionId,
|
||||
AttachmentType: feed.AttachmentTypeSubmission,
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.feed.CreateEvent(ctx, &event); err != nil {
|
||||
h.logger.Error("failed to create feed event",
|
||||
slog.String("agent_id", agentID),
|
||||
slog.String("error", err.Error()),
|
||||
slog.String("handler", handlerName),
|
||||
slog.String("submission_id", submissionId),
|
||||
slog.String("company_id", companyId),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||