Compare changes

Choose any two refs to compare.

+4320 -3537
+2
api/tangled/actorprofile.go
··· 18 18 // RECORDTYPE: ActorProfile 19 19 type ActorProfile struct { 20 20 LexiconTypeID string `json:"$type,const=sh.tangled.actor.profile" cborgen:"$type,const=sh.tangled.actor.profile"` 21 + // avatar: Small image to be displayed next to posts from account. AKA, 'profile picture' 22 + Avatar *util.LexBlob `json:"avatar,omitempty" cborgen:"avatar,omitempty"` 21 23 // bluesky: Include link to this account on Bluesky. 22 24 Bluesky bool `json:"bluesky" cborgen:"bluesky"` 23 25 // description: Free-form profile description text.
+44 -1
api/tangled/cbor_gen.go
··· 26 26 } 27 27 28 28 cw := cbg.NewCborWriter(w) 29 - fieldCount := 8 29 + fieldCount := 9 30 + 31 + if t.Avatar == nil { 32 + fieldCount-- 33 + } 30 34 31 35 if t.Description == nil { 32 36 fieldCount-- ··· 144 148 return err 145 149 } 146 150 151 + } 152 + } 153 + 154 + // t.Avatar (util.LexBlob) (struct) 155 + if t.Avatar != nil { 156 + 157 + if len("avatar") > 1000000 { 158 + return xerrors.Errorf("Value in field \"avatar\" was too long") 159 + } 160 + 161 + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("avatar"))); err != nil { 162 + return err 163 + } 164 + if _, err := cw.WriteString(string("avatar")); err != nil { 165 + return err 166 + } 167 + 168 + if err := t.Avatar.MarshalCBOR(cw); err != nil { 169 + return err 147 170 } 148 171 } 149 172 ··· 428 451 } 429 452 430 453 } 454 + } 455 + // t.Avatar (util.LexBlob) (struct) 456 + case "avatar": 457 + 458 + { 459 + 460 + b, err := cr.ReadByte() 461 + if err != nil { 462 + return err 463 + } 464 + if b != cbg.CborNull[0] { 465 + if err := cr.UnreadByte(); err != nil { 466 + return err 467 + } 468 + t.Avatar = new(util.LexBlob) 469 + if err := t.Avatar.UnmarshalCBOR(cr); err != nil { 470 + return xerrors.Errorf("unmarshaling t.Avatar pointer: %w", err) 471 + } 472 + } 473 + 431 474 } 432 475 // t.Bluesky (bool) (bool) 433 476 case "bluesky":
+9 -2
appview/db/db.go
··· 260 260 did text not null, 261 261 262 262 -- data 263 + avatar text, 263 264 description text not null, 264 265 include_bluesky integer not null default 0, 265 266 location text, ··· 565 566 from_at text not null, 566 567 to_at text not null, 567 568 unique (from_at, to_at) 569 + ); 570 + 571 + create table if not exists knot_preferences ( 572 + id integer primary key autoincrement, 573 + user_did text not null unique, 574 + default_knot text 568 575 ); 569 576 570 577 create table if not exists migrations ( ··· 1173 1180 return err 1174 1181 }) 1175 1182 1176 - orm.RunMigration(conn, logger, "add-punchcard-setting-profile", func(tx *sql.Tx) error { 1183 + orm.RunMigration(conn, logger, "add-avatar-to-profile", func(tx *sql.Tx) error { 1177 1184 _, err := tx.Exec(` 1178 - alter table profile add column punchard_setting string; 1185 + alter table profile add column avatar text; 1179 1186 `) 1180 1187 return err 1181 1188 })
+42
appview/db/preferences.go
··· 1 + package db 2 + 3 + import ( 4 + "database/sql" 5 + 6 + "tangled.org/core/appview/models" 7 + ) 8 + 9 + func GetKnotPreference(e Execer, did string) (*models.KnotPreference, error) { 10 + var knotPreference models.KnotPreference 11 + 12 + err := e.QueryRow( 13 + `select id, user_did, default_knot from knot_preferences where user_did = ?`, 14 + did, 15 + ).Scan(&knotPreference.ID, &knotPreference.Did, &knotPreference.DefaultKnot) 16 + if err == sql.ErrNoRows { 17 + return nil, nil 18 + } 19 + 20 + if err != nil { 21 + return nil, err 22 + } 23 + 24 + return &knotPreference, nil 25 + } 26 + 27 + func UpsertKnotPreference(e Execer, did, defaultKnot string) error { 28 + _, err := e.Exec( 29 + `insert or replace into knot_preferences ( 30 + user_did, 31 + default_knot 32 + ) 33 + values (?, ?)`, 34 + did, 35 + defaultKnot, 36 + ) 37 + if err != nil { 38 + return err 39 + } 40 + 41 + return nil 42 + }
+29 -32
appview/db/profile.go
··· 16 16 17 17 const TimeframeMonths = 7 18 18 19 - func MakeProfileTimeline(e Execer, forDid string, includePunchcard bool) (*models.ProfileTimeline, error) { 19 + func MakeProfileTimeline(e Execer, forDid string) (*models.ProfileTimeline, error) { 20 20 timeline := models.ProfileTimeline{ 21 21 ByMonth: make([]models.ByMonth, TimeframeMonths), 22 22 } ··· 98 98 }) 99 99 } 100 100 101 - if includePunchcard { 102 - punchcard, err := MakePunchcard( 103 - e, 104 - orm.FilterEq("did", forDid), 105 - orm.FilterGte("date", time.Now().AddDate(0, -TimeframeMonths, 0)), 106 - ) 107 - if err != nil { 108 - return nil, fmt.Errorf("error getting commits by did: %w", err) 101 + punchcard, err := MakePunchcard( 102 + e, 103 + orm.FilterEq("did", forDid), 104 + orm.FilterGte("date", time.Now().AddDate(0, -TimeframeMonths, 0)), 105 + ) 106 + if err != nil { 107 + return nil, fmt.Errorf("error getting commits by did: %w", err) 108 + } 109 + for _, punch := range punchcard.Punches { 110 + if punch.Date.After(now) { 111 + continue 109 112 } 110 - for _, punch := range punchcard.Punches { 111 - if punch.Date.After(now) { 112 - continue 113 - } 114 113 115 - monthsAgo := monthsBetween(punch.Date, now) 116 - if monthsAgo >= TimeframeMonths { 117 - // shouldn't happen; but times are weird 118 - continue 119 - } 114 + monthsAgo := monthsBetween(punch.Date, now) 115 + if monthsAgo >= TimeframeMonths { 116 + // shouldn't happen; but times are weird 117 + continue 118 + } 120 119 121 - idx := monthsAgo 122 - timeline.ByMonth[idx].Commits += punch.Count 123 - } 120 + idx := monthsAgo 121 + timeline.ByMonth[idx].Commits += punch.Count 124 122 } 125 123 126 124 return &timeline, nil ··· 160 158 _, err = tx.Exec( 161 159 `insert or replace into profile ( 162 160 did, 161 + avatar, 163 162 description, 164 163 include_bluesky, 165 164 location, 166 165 pronouns 167 166 ) 168 - values (?, ?, ?, ?, ?)`, 167 + values (?, ?, ?, ?, ?, ?)`, 169 168 profile.Did, 169 + profile.Avatar, 170 170 profile.Description, 171 171 includeBskyValue, 172 172 profile.Location, ··· 349 349 func GetProfile(e Execer, did string) (*models.Profile, error) { 350 350 var profile models.Profile 351 351 var pronouns sql.Null[string] 352 + var avatar sql.Null[string] 352 353 353 354 profile.Did = did 354 355 355 356 includeBluesky := 0 356 357 357 358 err := e.QueryRow( 358 - `select description, include_bluesky, location, pronouns, punchard_setting from profile where did = ?`, 359 + `select avatar, description, include_bluesky, location, pronouns from profile where did = ?`, 359 360 did, 360 - ).Scan(&profile.Description, &includeBluesky, &profile.Location, &pronouns, &profile.PunchardSetting) 361 + ).Scan(&avatar, &profile.Description, &includeBluesky, &profile.Location, &pronouns) 361 362 if err == sql.ErrNoRows { 362 363 profile := models.Profile{} 363 364 profile.Did = did ··· 374 375 375 376 if pronouns.Valid { 376 377 profile.Pronouns = pronouns.V 378 + } 379 + 380 + if avatar.Valid { 381 + profile.Avatar = avatar.V 377 382 } 378 383 379 384 rows, err := e.Query(`select link from profile_links where did = ?`, did) ··· 538 543 } 539 544 return nil 540 545 } 541 - 542 - func SetProfilePunchcardStatus(e Execer, did string, punchcard models.ProfilePunchcardOption) error { 543 - _, err := e.Exec( 544 - `update profile set punchard_setting = ? where did = ?`, 545 - punchcard, did, 546 - ) 547 - return err 548 - }
+6
appview/ingester.go
··· 285 285 return err 286 286 } 287 287 288 + avatar := "" 289 + if record.Avatar != nil { 290 + avatar = record.Avatar.Ref.String() 291 + } 292 + 288 293 description := "" 289 294 if record.Description != nil { 290 295 description = *record.Description ··· 325 330 326 331 profile := models.Profile{ 327 332 Did: did, 333 + Avatar: avatar, 328 334 Description: description, 329 335 IncludeBluesky: includeBluesky, 330 336 Location: location,
+8 -9
appview/issues/issues.go
··· 129 129 } 130 130 131 131 rp.pages.RepoSingleIssue(w, pages.RepoSingleIssueParams{ 132 - LoggedInUser: user, 133 - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 134 - Issue: issue, 135 - CommentList: issue.CommentList(), 136 - Backlinks: backlinks, 137 - OrderedReactionKinds: models.OrderedReactionKinds, 138 - Reactions: reactionMap, 139 - UserReacted: userReactions, 140 - LabelDefs: defs, 132 + LoggedInUser: user, 133 + RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 134 + Issue: issue, 135 + CommentList: issue.CommentList(), 136 + Backlinks: backlinks, 137 + Reactions: reactionMap, 138 + UserReacted: userReactions, 139 + LabelDefs: defs, 141 140 }) 142 141 } 143 142
+20 -19
appview/knots/knots.go
··· 40 40 Knotstream *eventconsumer.Consumer 41 41 } 42 42 43 - type tab = map[string]any 44 - 45 - var ( 46 - knotsTabs []tab = []tab{ 47 - {"Name": "profile", "Icon": "user"}, 48 - {"Name": "keys", "Icon": "key"}, 49 - {"Name": "emails", "Icon": "mail"}, 50 - {"Name": "notifications", "Icon": "bell"}, 51 - {"Name": "knots", "Icon": "volleyball"}, 52 - {"Name": "spindles", "Icon": "spool"}, 53 - } 54 - ) 55 - 56 43 func (k *Knots) Router() http.Handler { 57 44 r := chi.NewRouter() 58 45 ··· 81 68 return 82 69 } 83 70 71 + availableKnots, err := k.Enforcer.GetKnotsForUser(user.Did()) 72 + if err != nil { 73 + k.Logger.Error("failed to fetch available knots for user", "err", err) 74 + w.WriteHeader(http.StatusInternalServerError) 75 + return 76 + } 77 + 78 + defaultKnot := "" 79 + knotPrefence, err := db.GetKnotPreference(k.Db, user.Did()) 80 + if err != nil { 81 + k.Logger.Warn("gettings users knot preferences", "error", err) 82 + } 83 + if knotPrefence != nil { 84 + defaultKnot = knotPrefence.DefaultKnot 85 + } 86 + 84 87 k.Pages.Knots(w, pages.KnotsParams{ 85 - LoggedInUser: user, 86 - Registrations: registrations, 87 - Tabs: knotsTabs, 88 - Tab: "knots", 88 + LoggedInUser: user, 89 + Registrations: registrations, 90 + AvailableKnots: availableKnots, 91 + DefaultKnot: defaultKnot, 89 92 }) 90 93 } 91 94 ··· 148 151 Members: members, 149 152 Repos: repoMap, 150 153 IsOwner: true, 151 - Tabs: knotsTabs, 152 - Tab: "knots", 153 154 }) 154 155 } 155 156
+7
appview/models/preferences.go
··· 1 + package models 2 + 3 + type KnotPreference struct { 4 + ID int 5 + Did string 6 + DefaultKnot string 7 + }
+8 -26
appview/models/profile.go
··· 7 7 "tangled.org/core/api/tangled" 8 8 ) 9 9 10 - type ProfilePunchcardOption string 11 - 12 - const ( 13 - ProfilePunchcardOptionHideMine ProfilePunchcardOption = "HIDE_MINE" 14 - ProfilePunchcardOptionHideAll ProfilePunchcardOption = "HIDE_ALL" 15 - ) 16 - 17 - func ProfilePunchcardFromString(s string) ProfilePunchcardOption { 18 - switch s { 19 - case "HIDE_MINE": 20 - return ProfilePunchcardOptionHideMine 21 - case "HIDE_ALL": 22 - return ProfilePunchcardOptionHideAll 23 - default: 24 - return "" 25 - } 26 - } 27 - 28 10 type Profile struct { 29 11 // ids 30 12 ID int 31 13 Did string 32 14 33 15 // data 34 - Description string 35 - IncludeBluesky bool 36 - Location string 37 - Links [5]string 38 - Stats [2]VanityStat 39 - PinnedRepos [6]syntax.ATURI 40 - Pronouns string 41 - PunchardSetting ProfilePunchcardOption 16 + Avatar string // CID of the avatar blob 17 + Description string 18 + IncludeBluesky bool 19 + Location string 20 + Links [5]string 21 + Stats [2]VanityStat 22 + PinnedRepos [6]syntax.ATURI 23 + Pronouns string 42 24 } 43 25 44 26 func (p Profile) IsLinksEmpty() bool {
+4 -1
appview/models/repo.go
··· 130 130 131 131 // current display mode 132 132 ShowingRendered bool // currently in rendered mode 133 - ShowingText bool // currently in text/code mode 134 133 135 134 // content type flags 136 135 ContentType BlobContentType ··· 151 150 // no view available, only raw 152 151 return !(b.HasRenderedView || b.HasTextView) 153 152 } 153 + 154 + func (b BlobView) ShowingText() bool { 155 + return !b.ShowingRendered 156 + }
+52
appview/oauth/handler.go
··· 10 10 "slices" 11 11 "time" 12 12 13 + comatproto "github.com/bluesky-social/indigo/api/atproto" 13 14 "github.com/bluesky-social/indigo/atproto/auth/oauth" 15 + lexutil "github.com/bluesky-social/indigo/lex/util" 14 16 "github.com/go-chi/chi/v5" 15 17 "github.com/posthog/posthog-go" 16 18 "tangled.org/core/api/tangled" 17 19 "tangled.org/core/appview/db" 20 + "tangled.org/core/appview/models" 18 21 "tangled.org/core/consts" 19 22 "tangled.org/core/orm" 20 23 "tangled.org/core/tid" ··· 82 85 } 83 86 84 87 o.Logger.Debug("session saved successfully") 88 + 85 89 go o.addToDefaultKnot(sessData.AccountDID.String()) 86 90 go o.addToDefaultSpindle(sessData.AccountDID.String()) 91 + go o.ensureTangledProfile(sessData) 87 92 88 93 if !o.Config.Core.Dev { 89 94 err = o.Posthog.Enqueue(posthog.Capture{ ··· 187 192 } 188 193 189 194 l.Debug("successfully addeds to default Knot") 195 + } 196 + 197 + func (o *OAuth) ensureTangledProfile(sessData *oauth.ClientSessionData) { 198 + ctx := context.Background() 199 + did := sessData.AccountDID.String() 200 + l := o.Logger.With("did", did) 201 + 202 + _, err := db.GetProfile(o.Db, did) 203 + if err == nil { 204 + l.Debug("profile already exists in DB") 205 + return 206 + } 207 + 208 + l.Debug("creating empty Tangled profile") 209 + 210 + sess, err := o.ClientApp.ResumeSession(ctx, sessData.AccountDID, sessData.SessionID) 211 + if err != nil { 212 + l.Error("failed to resume session for profile creation", "err", err) 213 + return 214 + } 215 + client := sess.APIClient() 216 + 217 + _, err = comatproto.RepoPutRecord(ctx, client, &comatproto.RepoPutRecord_Input{ 218 + Collection: tangled.ActorProfileNSID, 219 + Repo: did, 220 + Rkey: "self", 221 + Record: &lexutil.LexiconTypeDecoder{Val: &tangled.ActorProfile{}}, 222 + }) 223 + 224 + if err != nil { 225 + l.Error("failed to create empty profile on PDS", "err", err) 226 + return 227 + } 228 + 229 + tx, err := o.Db.BeginTx(ctx, nil) 230 + if err != nil { 231 + l.Error("failed to start transaction", "err", err) 232 + return 233 + } 234 + 235 + emptyProfile := &models.Profile{Did: did} 236 + if err := db.UpsertProfile(tx, emptyProfile); err != nil { 237 + l.Error("failed to create empty profile in DB", "err", err) 238 + return 239 + } 240 + 241 + l.Debug("successfully created empty Tangled profile on PDS and DB") 190 242 } 191 243 192 244 // create a session using apppasswords
+2 -2
appview/oauth/oauth.go
··· 41 41 if config.Core.Dev { 42 42 clientUri = "http://127.0.0.1:3000" 43 43 callbackUri := clientUri + "/oauth/callback" 44 - oauthConfig = oauth.NewLocalhostConfig(callbackUri, []string{"atproto", "transition:generic"}) 44 + oauthConfig = oauth.NewLocalhostConfig(callbackUri, TangledScopes) 45 45 } else { 46 46 clientUri = config.Core.AppviewHost 47 47 clientId := fmt.Sprintf("%s/oauth/client-metadata.json", clientUri) 48 48 callbackUri := clientUri + "/oauth/callback" 49 - oauthConfig = oauth.NewPublicConfig(clientId, callbackUri, []string{"atproto", "transition:generic"}) 49 + oauthConfig = oauth.NewPublicConfig(clientId, callbackUri, TangledScopes) 50 50 } 51 51 52 52 // configure client secret
+41
appview/oauth/scopes.go
··· 1 + package oauth 2 + 3 + var TangledScopes = []string{ 4 + "atproto", 5 + 6 + "repo:sh.tangled.publicKey", 7 + "repo:sh.tangled.repo", 8 + "repo:sh.tangled.repo.pull", 9 + "repo:sh.tangled.repo.pull.comment", 10 + "repo:sh.tangled.repo.artifact", 11 + "repo:sh.tangled.repo.issue", 12 + "repo:sh.tangled.repo.issue.comment", 13 + "repo:sh.tangled.repo.collaborator", 14 + "repo:sh.tangled.knot", 15 + "repo:sh.tangled.knot.member", 16 + "repo:sh.tangled.spindle", 17 + "repo:sh.tangled.spindle.member", 18 + "repo:sh.tangled.graph.follow", 19 + "repo:sh.tangled.feed.star", 20 + "repo:sh.tangled.feed.reaction", 21 + "repo:sh.tangled.label.definition", 22 + "repo:sh.tangled.label.op", 23 + "repo:sh.tangled.string", 24 + "repo:sh.tangled.actor.profile", 25 + 26 + "blob:*/*", 27 + 28 + "rpc:sh.tangled.repo.create?aud=*", 29 + "rpc:sh.tangled.repo.delete?aud=*", 30 + "rpc:sh.tangled.repo.merge?aud=*", 31 + "rpc:sh.tangled.repo.hiddenRef?aud=*", 32 + "rpc:sh.tangled.repo.deleteBranch?aud=*", 33 + "rpc:sh.tangled.repo.setDefaultBranch?aud=*", 34 + "rpc:sh.tangled.repo.forkSync?aud=*", 35 + "rpc:sh.tangled.repo.forkStatus?aud=*", 36 + "rpc:sh.tangled.repo.mergeCheck?aud=*", 37 + "rpc:sh.tangled.pipeline.cancelPipeline?aud=*", 38 + "rpc:sh.tangled.repo.addSecret?aud=*", 39 + "rpc:sh.tangled.repo.removeSecret?aud=*", 40 + "rpc:sh.tangled.repo.listSecrets?aud=*", 41 + }
+94 -7
appview/pages/funcmap.go
··· 26 26 "github.com/go-enry/go-enry/v2" 27 27 "github.com/yuin/goldmark" 28 28 emoji "github.com/yuin/goldmark-emoji" 29 + "tangled.org/core/appview/db" 29 30 "tangled.org/core/appview/models" 30 31 "tangled.org/core/appview/oauth" 31 32 "tangled.org/core/appview/pages/markup" 32 33 "tangled.org/core/crypto" 33 34 ) 35 + 36 + type tab map[string]string 34 37 35 38 func (p *Pages) funcMap() template.FuncMap { 36 39 return template.FuncMap{ ··· 332 335 } 333 336 return dict, nil 334 337 }, 338 + "queryParams": func(params ...any) (url.Values, error) { 339 + if len(params)%2 != 0 { 340 + return nil, errors.New("invalid queryParams call") 341 + } 342 + vals := make(url.Values, len(params)/2) 343 + for i := 0; i < len(params); i += 2 { 344 + key, ok := params[i].(string) 345 + if !ok { 346 + return nil, errors.New("queryParams keys must be strings") 347 + } 348 + v, ok := params[i+1].(string) 349 + if !ok { 350 + return nil, errors.New("queryParams values must be strings") 351 + } 352 + vals.Add(key, v) 353 + } 354 + return vals, nil 355 + }, 335 356 "deref": func(v any) any { 336 357 val := reflect.ValueOf(v) 337 358 if val.Kind() == reflect.Pointer && !val.IsNil() { ··· 364 385 "fullAvatar": func(handle string) string { 365 386 return p.AvatarUrl(handle, "") 366 387 }, 388 + "placeholderAvatar": func(size string) template.HTML { 389 + sizeClass := "size-6" 390 + iconSize := "size-4" 391 + if size == "tiny" { 392 + sizeClass = "size-6" 393 + iconSize = "size-4" 394 + } else if size == "small" { 395 + sizeClass = "size-8" 396 + iconSize = "size-5" 397 + } else { 398 + sizeClass = "size-12" 399 + iconSize = "size-8" 400 + } 401 + icon, _ := p.icon("user-round", []string{iconSize, "text-gray-400", "dark:text-gray-500"}) 402 + return template.HTML(fmt.Sprintf(`<div class="%s rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center flex-shrink-0">%s</div>`, sizeClass, icon)) 403 + }, 404 + "profileAvatarUrl": func(profile *models.Profile, size string) string { 405 + if profile != nil { 406 + return p.AvatarUrl(profile.Did, size) 407 + } 408 + return "" 409 + }, 367 410 "langColor": enry.GetColor, 368 411 "reverse": func(s any) any { 369 412 if s == nil { ··· 406 449 } 407 450 return result 408 451 }, 452 + // constant values used to define a template 453 + "const": func() map[string]any { 454 + return map[string]any{ 455 + "OrderedReactionKinds": models.OrderedReactionKinds, 456 + // would be great to have ordered maps right about now 457 + "UserSettingsTabs": []tab{ 458 + {"Name": "profile", "Icon": "user"}, 459 + {"Name": "keys", "Icon": "key"}, 460 + {"Name": "emails", "Icon": "mail"}, 461 + {"Name": "notifications", "Icon": "bell"}, 462 + {"Name": "knots", "Icon": "volleyball"}, 463 + {"Name": "spindles", "Icon": "spool"}, 464 + }, 465 + "RepoSettingsTabs": []tab{ 466 + {"Name": "general", "Icon": "sliders-horizontal"}, 467 + {"Name": "access", "Icon": "users"}, 468 + {"Name": "pipelines", "Icon": "layers-2"}, 469 + }, 470 + } 471 + }, 409 472 } 410 473 } 411 474 ··· 423 486 return identity.Handle.String() 424 487 } 425 488 426 - func (p *Pages) AvatarUrl(handle, size string) string { 427 - handle = strings.TrimPrefix(handle, "@") 489 + func (p *Pages) AvatarUrl(actor, size string) string { 490 + actor = strings.TrimPrefix(actor, "@") 428 491 429 - handle = p.resolveDid(handle) 492 + identity, err := p.resolver.ResolveIdent(context.Background(), actor) 493 + var did string 494 + if err != nil { 495 + did = actor 496 + } else { 497 + did = identity.DID.String() 498 + } 430 499 431 500 secret := p.avatar.SharedSecret 432 501 h := hmac.New(sha256.New, []byte(secret)) 433 - h.Write([]byte(handle)) 502 + h.Write([]byte(did)) 434 503 signature := hex.EncodeToString(h.Sum(nil)) 435 504 436 - sizeArg := "" 505 + // Get avatar CID for cache busting 506 + profile, err := db.GetProfile(p.db, did) 507 + version := "" 508 + if err == nil && profile != nil && profile.Avatar != "" { 509 + // Use first 8 chars of avatar CID as version 510 + if len(profile.Avatar) > 8 { 511 + version = profile.Avatar[:8] 512 + } else { 513 + version = profile.Avatar 514 + } 515 + } 516 + 517 + baseUrl := fmt.Sprintf("%s/%s/%s", p.avatar.Host, signature, did) 437 518 if size != "" { 438 - sizeArg = fmt.Sprintf("size=%s", size) 519 + if version != "" { 520 + return fmt.Sprintf("%s?size=%s&v=%s", baseUrl, size, version) 521 + } 522 + return fmt.Sprintf("%s?size=%s", baseUrl, size) 439 523 } 440 - return fmt.Sprintf("%s/%s/%s?%s", p.avatar.Host, signature, handle, sizeArg) 524 + if version != "" { 525 + return fmt.Sprintf("%s?v=%s", baseUrl, version) 526 + } 527 + return baseUrl 441 528 } 442 529 443 530 func (p *Pages) icon(name string, classes []string) (template.HTML, error) {
+1 -1
appview/pages/funcmap_test.go
··· 22 22 } 23 23 for _, tt := range tests { 24 24 t.Run(tt.name, func(t *testing.T) { 25 - p := NewPages(tt.config, tt.res, tt.l) 25 + p := NewPages(tt.config, tt.res, nil, tt.l) 26 26 got := p.funcMap() 27 27 // TODO: update the condition below to compare got with tt.want. 28 28 if true {
+41 -43
appview/pages/pages.go
··· 19 19 "tangled.org/core/api/tangled" 20 20 "tangled.org/core/appview/commitverify" 21 21 "tangled.org/core/appview/config" 22 + "tangled.org/core/appview/db" 22 23 "tangled.org/core/appview/models" 23 24 "tangled.org/core/appview/oauth" 24 25 "tangled.org/core/appview/pages/markup" ··· 42 43 43 44 avatar config.AvatarConfig 44 45 resolver *idresolver.Resolver 46 + db *db.DB 45 47 dev bool 46 48 embedFS fs.FS 47 49 templateDir string // Path to templates on disk for dev mode ··· 49 51 logger *slog.Logger 50 52 } 51 53 52 - func NewPages(config *config.Config, res *idresolver.Resolver, logger *slog.Logger) *Pages { 54 + func NewPages(config *config.Config, res *idresolver.Resolver, database *db.DB, logger *slog.Logger) *Pages { 53 55 // initialized with safe defaults, can be overriden per use 54 56 rctx := &markup.RenderContext{ 55 57 IsDev: config.Core.Dev, ··· 66 68 avatar: config.Avatar, 67 69 rctx: rctx, 68 70 resolver: res, 71 + db: database, 69 72 templateDir: "appview/pages", 70 73 logger: logger, 71 74 } ··· 337 340 } 338 341 339 342 type UserProfileSettingsParams struct { 340 - LoggedInUser *oauth.MultiAccountUser 341 - Tabs []map[string]any 342 - Tab string 343 - PunchcardSetting models.ProfilePunchcardOption 343 + LoggedInUser *oauth.MultiAccountUser 344 + Tab string 344 345 } 345 346 346 347 func (p *Pages) UserProfileSettings(w io.Writer, params UserProfileSettingsParams) error { 348 + params.Tab = "profile" 347 349 return p.execute("user/settings/profile", w, params) 348 350 } 349 351 ··· 378 380 type UserKeysSettingsParams struct { 379 381 LoggedInUser *oauth.MultiAccountUser 380 382 PubKeys []models.PublicKey 381 - Tabs []map[string]any 382 383 Tab string 383 384 } 384 385 385 386 func (p *Pages) UserKeysSettings(w io.Writer, params UserKeysSettingsParams) error { 387 + params.Tab = "keys" 386 388 return p.execute("user/settings/keys", w, params) 387 389 } 388 390 389 391 type UserEmailsSettingsParams struct { 390 392 LoggedInUser *oauth.MultiAccountUser 391 393 Emails []models.Email 392 - Tabs []map[string]any 393 394 Tab string 394 395 } 395 396 396 397 func (p *Pages) UserEmailsSettings(w io.Writer, params UserEmailsSettingsParams) error { 398 + params.Tab = "emails" 397 399 return p.execute("user/settings/emails", w, params) 398 400 } 399 401 400 402 type UserNotificationSettingsParams struct { 401 403 LoggedInUser *oauth.MultiAccountUser 402 404 Preferences *models.NotificationPreferences 403 - Tabs []map[string]any 404 405 Tab string 405 406 } 406 407 407 408 func (p *Pages) UserNotificationSettings(w io.Writer, params UserNotificationSettingsParams) error { 409 + params.Tab = "notifications" 408 410 return p.execute("user/settings/notifications", w, params) 409 411 } 410 412 ··· 418 420 } 419 421 420 422 type KnotsParams struct { 421 - LoggedInUser *oauth.MultiAccountUser 422 - Registrations []models.Registration 423 - Tabs []map[string]any 424 - Tab string 423 + LoggedInUser *oauth.MultiAccountUser 424 + Registrations []models.Registration 425 + Tab string 426 + AvailableKnots []string 427 + DefaultKnot string 425 428 } 426 429 427 430 func (p *Pages) Knots(w io.Writer, params KnotsParams) error { 431 + params.Tab = "knots" 428 432 return p.execute("knots/index", w, params) 429 433 } 430 434 ··· 434 438 Members []string 435 439 Repos map[string][]models.Repo 436 440 IsOwner bool 437 - Tabs []map[string]any 438 441 Tab string 439 442 } 440 443 ··· 453 456 type SpindlesParams struct { 454 457 LoggedInUser *oauth.MultiAccountUser 455 458 Spindles []models.Spindle 456 - Tabs []map[string]any 457 459 Tab string 458 460 } 459 461 460 462 func (p *Pages) Spindles(w io.Writer, params SpindlesParams) error { 463 + params.Tab = "spindles" 461 464 return p.execute("spindles/index", w, params) 462 465 } 463 466 464 467 type SpindleListingParams struct { 465 468 models.Spindle 466 - Tabs []map[string]any 467 - Tab string 469 + Tab string 468 470 } 469 471 470 472 func (p *Pages) SpindleListing(w io.Writer, params SpindleListingParams) error { ··· 476 478 Spindle models.Spindle 477 479 Members []string 478 480 Repos map[string][]models.Repo 479 - Tabs []map[string]any 480 481 Tab string 481 482 } 482 483 ··· 487 488 type NewRepoParams struct { 488 489 LoggedInUser *oauth.MultiAccountUser 489 490 Knots []string 491 + DefaultKnot string 490 492 } 491 493 492 494 func (p *Pages) NewRepo(w io.Writer, params NewRepoParams) error { ··· 497 499 LoggedInUser *oauth.MultiAccountUser 498 500 Knots []string 499 501 RepoInfo repoinfo.RepoInfo 502 + DefaultKnot string 500 503 } 501 504 502 505 func (p *Pages) ForkRepo(w io.Writer, params ForkRepoParams) error { ··· 538 541 ProfileTimeline *models.ProfileTimeline 539 542 Card *ProfileCard 540 543 Active string 541 - ShowPunchcard bool 542 544 } 543 545 544 546 func (p *Pages) ProfileOverview(w io.Writer, params ProfileOverviewParams) error { ··· 888 890 SubscribedLabels map[string]struct{} 889 891 ShouldSubscribeAll bool 890 892 Active string 891 - Tabs []map[string]any 892 893 Tab string 893 894 Branches []types.Branch 894 895 } 895 896 896 897 func (p *Pages) RepoGeneralSettings(w io.Writer, params RepoGeneralSettingsParams) error { 897 898 params.Active = "settings" 899 + params.Tab = "general" 898 900 return p.executeRepo("repo/settings/general", w, params) 899 901 } 900 902 ··· 902 904 LoggedInUser *oauth.MultiAccountUser 903 905 RepoInfo repoinfo.RepoInfo 904 906 Active string 905 - Tabs []map[string]any 906 907 Tab string 907 908 Collaborators []Collaborator 908 909 } 909 910 910 911 func (p *Pages) RepoAccessSettings(w io.Writer, params RepoAccessSettingsParams) error { 911 912 params.Active = "settings" 913 + params.Tab = "access" 912 914 return p.executeRepo("repo/settings/access", w, params) 913 915 } 914 916 ··· 916 918 LoggedInUser *oauth.MultiAccountUser 917 919 RepoInfo repoinfo.RepoInfo 918 920 Active string 919 - Tabs []map[string]any 920 921 Tab string 921 922 Spindles []string 922 923 CurrentSpindle string ··· 925 926 926 927 func (p *Pages) RepoPipelineSettings(w io.Writer, params RepoPipelineSettingsParams) error { 927 928 params.Active = "settings" 929 + params.Tab = "pipelines" 928 930 return p.executeRepo("repo/settings/pipelines", w, params) 929 931 } 930 932 ··· 954 956 Backlinks []models.RichReferenceLink 955 957 LabelDefs map[string]*models.LabelDefinition 956 958 957 - OrderedReactionKinds []models.ReactionKind 958 - Reactions map[models.ReactionKind]models.ReactionDisplayData 959 - UserReacted map[models.ReactionKind]bool 959 + Reactions map[models.ReactionKind]models.ReactionDisplayData 960 + UserReacted map[models.ReactionKind]bool 960 961 } 961 962 962 963 func (p *Pages) RepoSingleIssue(w io.Writer, params RepoSingleIssueParams) error { ··· 1117 1118 ActiveRound int 1118 1119 IsInterdiff bool 1119 1120 1120 - OrderedReactionKinds []models.ReactionKind 1121 - Reactions map[models.ReactionKind]models.ReactionDisplayData 1122 - UserReacted map[models.ReactionKind]bool 1121 + Reactions map[models.ReactionKind]models.ReactionDisplayData 1122 + UserReacted map[models.ReactionKind]bool 1123 1123 1124 1124 LabelDefs map[string]*models.LabelDefinition 1125 1125 } ··· 1130 1130 } 1131 1131 1132 1132 type RepoPullPatchParams struct { 1133 - LoggedInUser *oauth.MultiAccountUser 1134 - RepoInfo repoinfo.RepoInfo 1135 - Pull *models.Pull 1136 - Stack models.Stack 1137 - Diff *types.NiceDiff 1138 - Round int 1139 - Submission *models.PullSubmission 1140 - OrderedReactionKinds []models.ReactionKind 1141 - DiffOpts types.DiffOpts 1133 + LoggedInUser *oauth.MultiAccountUser 1134 + RepoInfo repoinfo.RepoInfo 1135 + Pull *models.Pull 1136 + Stack models.Stack 1137 + Diff *types.NiceDiff 1138 + Round int 1139 + Submission *models.PullSubmission 1140 + DiffOpts types.DiffOpts 1142 1141 } 1143 1142 1144 1143 // this name is a mouthful ··· 1147 1146 } 1148 1147 1149 1148 type RepoPullInterdiffParams struct { 1150 - LoggedInUser *oauth.MultiAccountUser 1151 - RepoInfo repoinfo.RepoInfo 1152 - Pull *models.Pull 1153 - Round int 1154 - Interdiff *patchutil.InterdiffResult 1155 - OrderedReactionKinds []models.ReactionKind 1156 - DiffOpts types.DiffOpts 1149 + LoggedInUser *oauth.MultiAccountUser 1150 + RepoInfo repoinfo.RepoInfo 1151 + Pull *models.Pull 1152 + Round int 1153 + Interdiff *patchutil.InterdiffResult 1154 + DiffOpts types.DiffOpts 1157 1155 } 1158 1156 1159 1157 // this name is a mouthful
+2 -2
appview/pages/templates/fragments/pagination.html
··· 1 1 {{ define "fragments/pagination" }} 2 - {{/* Params: Page (pagination.Page), TotalCount (int), BasePath (string), QueryParams (string) */}} 2 + {{/* Params: Page (pagination.Page), TotalCount (int), BasePath (string), QueryParams (url.Values) */}} 3 3 {{ $page := .Page }} 4 4 {{ $totalCount := .TotalCount }} 5 5 {{ $basePath := .BasePath }} 6 - {{ $queryParams := .QueryParams }} 6 + {{ $queryParams := safeUrl .QueryParams.Encode }} 7 7 8 8 {{ $prev := $page.Previous.Offset }} 9 9 {{ $next := $page.Next.Offset }}
+28
appview/pages/templates/knots/index.html
··· 31 31 <div class="flex flex-col gap-6"> 32 32 {{ block "list" . }} {{ end }} 33 33 {{ block "register" . }} {{ end }} 34 + {{ block "default-knot" . }} {{ end }} 34 35 </div> 35 36 </section> 36 37 {{ end }} ··· 60 61 </div> 61 62 <div id="operation-error" class="text-red-500 dark:text-red-400"></div> 62 63 </section> 64 + {{ end }} 65 + 66 + {{ define "default-knot" }} 67 + <section class="rounded w-full flex flex-col gap-2"> 68 + <h2 class="text-sm font-bold py-2 uppercase dark:text-gray-300">default knot</h2> 69 + <form hx-post="/profile/default-knot" class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch"> 70 + <select 71 + id="default-knot" 72 + name="default-knot" 73 + required 74 + class="p-1 max-w-64 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700"> 75 + {{/* For some reason, we can't use an empty string in a <select> in all scenarios unless it is preceded by a disabled select?? No idea, could just be a Firefox thing? */}} 76 + <option value="[[none]]" class="py-1" {{ if not $.DefaultKnot }}selected{{ end }}> 77 + Choose a default knot 78 + </option> 79 + {{ range $.AvailableKnots }} 80 + <option value="{{ . }}" class="py-1" {{ if eq . $.DefaultKnot }}selected{{ end }}> 81 + {{ . }} 82 + </option> 83 + {{ end }} 84 + </select> 85 + <button class="btn flex gap-2 items-center" type="submit"> 86 + {{ i "check" "size-4" }} 87 + {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 88 + </button> 89 + </form> 90 + </section> 63 91 {{ end }} 64 92 65 93 {{ define "register" }}
+3 -5
appview/pages/templates/layouts/profilebase.html
··· 2 2 3 3 {{ define "extrameta" }} 4 4 {{ $handle := resolve .Card.UserDid }} 5 - {{ $avatarUrl := fullAvatar $handle }} 5 + {{ $avatarUrl := profileAvatarUrl .Card.Profile "" }} 6 6 <meta property="og:title" content="{{ $handle }}" /> 7 7 <meta property="og:type" content="profile" /> 8 8 <meta property="og:url" content="https://tangled.org/{{ $handle }}?tab={{ .Active }}" /> ··· 10 10 <meta property="og:image" content="{{ $avatarUrl }}" /> 11 11 <meta property="og:image:width" content="512" /> 12 12 <meta property="og:image:height" content="512" /> 13 - 13 + 14 14 <meta name="twitter:card" content="summary" /> 15 15 <meta name="twitter:title" content="{{ $handle }}" /> 16 16 <meta name="twitter:description" content="{{ or .Card.Profile.Description $handle }}" /> ··· 28 28 <div class="{{ $style }} order-1 order-1"> 29 29 <div class="flex flex-col gap-4"> 30 30 {{ template "user/fragments/profileCard" .Card }} 31 - {{ if .ShowPunchcard }} 32 - {{ block "punchcard" .Card.Punchcard }} {{ end }} 33 - {{ end }} 31 + {{ block "punchcard" .Card.Punchcard }} {{ end }} 34 32 </div> 35 33 </div> 36 34
+1 -1
appview/pages/templates/repo/blob.html
··· 35 35 36 36 {{ if .BlobView.ShowingText }} 37 37 <span class="select-none px-1 md:px-2 [&:before]:content-['ยท']"></span> 38 - <span>{{ .Lines }} lines</span> 38 + <span>{{ .BlobView.Lines }} lines</span> 39 39 {{ end }} 40 40 41 41 {{ if .BlobView.SizeHint }}
+4 -1
appview/pages/templates/repo/commit.html
··· 100 100 {{ if $did }} 101 101 {{ template "user/fragments/picHandleLink" $did }} 102 102 {{ else }} 103 - <a href="mailto:{{ $email }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ $name }}</a> 103 + <span class="flex items-center gap-1"> 104 + {{ placeholderAvatar "tiny" }} 105 + <a href="mailto:{{ $email }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ $name }}</a> 106 + </span> 104 107 {{ end }} 105 108 {{ end }} 106 109
+3 -1
appview/pages/templates/repo/fork.html
··· 25 25 value="{{ . }}" 26 26 class="mr-2" 27 27 id="domain-{{ . }}" 28 - {{if eq (len $.Knots) 1}}checked{{end}} 28 + {{if eq (len $.Knots) 1}}checked 29 + {{else if eq $.DefaultKnot . }}checked 30 + {{end}} 29 31 /> 30 32 <label for="domain-{{ . }}" class="dark:text-white">{{ . }}</label> 31 33 </div>
+50
appview/pages/templates/repo/fragments/reactions.html
··· 1 + {{ define "repo/fragments/reactions" }} 2 + <div class="flex flex-wrap items-center gap-2"> 3 + {{- $reactions := .Reactions -}} 4 + {{- $userReacted := .UserReacted -}} 5 + {{- $threadAt := .ThreadAt -}} 6 + 7 + {{ template "reactionsPopup" }} 8 + {{ range $kind := const.OrderedReactionKinds }} 9 + {{ $reactionData := index $reactions $kind }} 10 + {{ template "repo/fragments/reaction" 11 + (dict 12 + "Kind" $kind 13 + "Count" $reactionData.Count 14 + "IsReacted" (index $userReacted $kind) 15 + "ThreadAt" $threadAt 16 + "Users" $reactionData.Users) }} 17 + {{ end }} 18 + </div> 19 + {{ end }} 20 + 21 + {{ define "reactionsPopup" }} 22 + <details 23 + id="reactionsPopUp" 24 + class="relative inline-block" 25 + > 26 + <summary 27 + class="flex justify-center items-center min-w-8 min-h-8 rounded border border-gray-200 dark:border-gray-700 28 + hover:bg-gray-50 29 + hover:border-gray-300 30 + dark:hover:bg-gray-700 31 + dark:hover:border-gray-600 32 + cursor-pointer list-none" 33 + > 34 + {{ i "smile" "size-4" }} 35 + </summary> 36 + <div 37 + class="absolute flex left-0 z-10 mt-4 rounded bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700 shadow-lg" 38 + > 39 + {{ range $kind := const.OrderedReactionKinds }} 40 + <button 41 + id="reactBtn-{{ $kind }}" 42 + class="size-12 hover:bg-gray-100 dark:hover:bg-gray-700" 43 + hx-on:click="this.parentElement.parentElement.removeAttribute('open')" 44 + > 45 + {{ $kind }} 46 + </button> 47 + {{ end }} 48 + </div> 49 + </details> 50 + {{ end }}
-30
appview/pages/templates/repo/fragments/reactionsPopUp.html
··· 1 - {{ define "repo/fragments/reactionsPopUp" }} 2 - <details 3 - id="reactionsPopUp" 4 - class="relative inline-block" 5 - > 6 - <summary 7 - class="flex justify-center items-center min-w-8 min-h-8 rounded border border-gray-200 dark:border-gray-700 8 - hover:bg-gray-50 9 - hover:border-gray-300 10 - dark:hover:bg-gray-700 11 - dark:hover:border-gray-600 12 - cursor-pointer list-none" 13 - > 14 - {{ i "smile" "size-4" }} 15 - </summary> 16 - <div 17 - class="absolute flex left-0 z-10 mt-4 rounded bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700 shadow-lg" 18 - > 19 - {{ range $kind := . }} 20 - <button 21 - id="reactBtn-{{ $kind }}" 22 - class="size-12 hover:bg-gray-100 dark:hover:bg-gray-700" 23 - hx-on:click="this.parentElement.parentElement.removeAttribute('open')" 24 - > 25 - {{ $kind }} 26 - </button> 27 - {{ end }} 28 - </div> 29 - </details> 30 - {{ end }}
+6 -2
appview/pages/templates/repo/index.html
··· 254 254 {{ define "attribution" }} 255 255 {{ $commit := index . 0 }} 256 256 {{ $map := index . 1 }} 257 - <span class="flex items-center"> 257 + <span class="flex items-center gap-1"> 258 258 {{ $author := index $map $commit.Author.Email }} 259 259 {{ $coauthors := $commit.CoAuthors }} 260 260 {{ $all := list }} ··· 269 269 {{ end }} 270 270 {{ end }} 271 271 272 - {{ template "fragments/tinyAvatarList" (dict "all" $all "classes" "size-6") }} 272 + {{ if $author }} 273 + {{ template "fragments/tinyAvatarList" (dict "all" $all "classes" "size-6") }} 274 + {{ else }} 275 + {{ placeholderAvatar "tiny" }} 276 + {{ end }} 273 277 <a href="{{ if $author }}/{{ $author }}{{ else }}mailto:{{ $commit.Author.Email }}{{ end }}" 274 278 class="no-underline hover:underline"> 275 279 {{ if $author }}{{ resolve $author }}{{ else }}{{ $commit.Author.Name }}{{ end }}
+2 -1
appview/pages/templates/repo/issues/fragments/issueCommentHeader.html
··· 1 1 {{ define "repo/issues/fragments/issueCommentHeader" }} 2 2 <div class="flex flex-wrap items-center gap-2 text-sm text-gray-500 dark:text-gray-400 "> 3 - {{ resolve .Comment.Did }} 3 + {{ $handle := resolve .Comment.Did }} 4 + <a class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" href="/{{ $handle }}">{{ $handle }}</a> 4 5 {{ template "hats" $ }} 5 6 <span class="before:content-['ยท']"></span> 6 7 {{ template "timestamp" . }}
+1 -1
appview/pages/templates/repo/issues/fragments/newComment.html
··· 12 12 <textarea 13 13 id="comment-textarea" 14 14 name="body" 15 - class="w-full p-2 rounded border border-gray-200 dark:border-gray-700" 15 + class="w-full p-2 rounded" 16 16 placeholder="Add to the discussion. Markdown is supported." 17 17 onkeyup="updateCommentForm()" 18 18 rows="5"
+1 -1
appview/pages/templates/repo/issues/fragments/replyIssueCommentPlaceholder.html
··· 8 8 /> 9 9 {{ end }} 10 10 <input 11 - class="w-full p-0 border-none focus:outline-none" 11 + class="w-full p-0 border-none focus:outline-none bg-transparent" 12 12 placeholder="Leave a reply..." 13 13 hx-get="/{{ .RepoInfo.FullName }}/issues/{{ .Issue.IssueId }}/comment/{{ .Comment.Id }}/reply" 14 14 hx-trigger="focus"
+5 -21
appview/pages/templates/repo/issues/issue.html
··· 35 35 {{ if .Issue.Body }} 36 36 <article id="body" class="mt-4 prose dark:prose-invert">{{ .Issue.Body | markdown }}</article> 37 37 {{ end }} 38 - <div class="flex flex-wrap gap-2 items-stretch mt-4"> 39 - {{ template "issueReactions" . }} 38 + <div class="mt-4"> 39 + {{ template "repo/fragments/reactions" 40 + (dict "Reactions" .Reactions 41 + "UserReacted" .UserReacted 42 + "ThreadAt" .Issue.AtUri) }} 40 43 </div> 41 44 </section> 42 45 {{ end }} ··· 106 109 {{ i "loader-circle" "size-3 animate-spin hidden group-[.htmx-request]:inline" }} 107 110 </a> 108 111 {{ end }} 109 - 110 - {{ define "issueReactions" }} 111 - <div class="flex items-center gap-2"> 112 - {{ template "repo/fragments/reactionsPopUp" .OrderedReactionKinds }} 113 - {{ range $kind := .OrderedReactionKinds }} 114 - {{ $reactionData := index $.Reactions $kind }} 115 - {{ 116 - template "repo/fragments/reaction" 117 - (dict 118 - "Kind" $kind 119 - "Count" $reactionData.Count 120 - "IsReacted" (index $.UserReacted $kind) 121 - "ThreadAt" $.Issue.AtUri 122 - "Users" $reactionData.Users) 123 - }} 124 - {{ end }} 125 - </div> 126 - {{ end }} 127 - 128 112 129 113 {{ define "repoAfter" }} 130 114 <div class="flex flex-col gap-4 mt-4">
+1 -1
appview/pages/templates/repo/issues/issues.html
··· 80 80 "Page" .Page 81 81 "TotalCount" .IssueCount 82 82 "BasePath" (printf "/%s/issues" .RepoInfo.FullName) 83 - "QueryParams" (printf "state=%s&q=%s" $state .FilterQuery) 83 + "QueryParams" (queryParams "state" $state "q" .FilterQuery) 84 84 ) }} 85 85 {{ end }} 86 86 {{ end }}
+5 -1
appview/pages/templates/repo/log.html
··· 186 186 {{ end }} 187 187 {{ end }} 188 188 189 - {{ template "fragments/tinyAvatarList" (dict "all" $all "classes" "size-6") }} 189 + {{ if $author }} 190 + {{ template "fragments/tinyAvatarList" (dict "all" $all "classes" "size-6") }} 191 + {{ else }} 192 + {{ placeholderAvatar "tiny" }} 193 + {{ end }} 190 194 <a href="{{ if $author }}/{{ $author }}{{ else }}mailto:{{ $commit.Author.Email }}{{ end }}" 191 195 class="no-underline hover:underline"> 192 196 {{ if $author }}{{ resolve $author }}{{ else }}{{ $commit.Author.Name }}{{ end }}
+3 -1
appview/pages/templates/repo/new.html
··· 155 155 class="mr-2" 156 156 id="domain-{{ . }}" 157 157 required 158 - {{if eq (len $.Knots) 1}}checked{{end}} 158 + {{if eq (len $.Knots) 1}}checked 159 + {{else if eq $.DefaultKnot . }}checked 160 + {{end}} 159 161 /> 160 162 <label for="domain-{{ . }}" class="dark:text-white lowercase">{{ . }}</label> 161 163 </div>
+5 -16
appview/pages/templates/repo/pulls/fragments/pullHeader.html
··· 63 63 </article> 64 64 {{ end }} 65 65 66 - {{ with .OrderedReactionKinds }} 67 - <div class="flex items-center gap-2 mt-2"> 68 - {{ template "repo/fragments/reactionsPopUp" . }} 69 - {{ range $kind := . }} 70 - {{ $reactionData := index $.Reactions $kind }} 71 - {{ 72 - template "repo/fragments/reaction" 73 - (dict 74 - "Kind" $kind 75 - "Count" $reactionData.Count 76 - "IsReacted" (index $.UserReacted $kind) 77 - "ThreadAt" $.Pull.AtUri 78 - "Users" $reactionData.Users) 79 - }} 80 - {{ end }} 66 + <div class="mt-2"> 67 + {{ template "repo/fragments/reactions" 68 + (dict "Reactions" .Reactions 69 + "UserReacted" .UserReacted 70 + "ThreadAt" .Pull.AtUri) }} 81 71 </div> 82 - {{ end }} 83 72 </section> 84 73 85 74
+1 -1
appview/pages/templates/repo/pulls/fragments/pullNewComment.html
··· 12 12 > 13 13 <textarea 14 14 name="body" 15 - class="w-full p-2 rounded border border-gray-200" 15 + class="w-full p-2 rounded border" 16 16 rows=8 17 17 placeholder="Add to the discussion..."></textarea 18 18 >
+111 -58
appview/pages/templates/repo/pulls/pull.html
··· 22 22 <script> 23 23 (function() { 24 24 const details = document.getElementById('bottomSheet'); 25 + const backdrop = document.getElementById('bottomSheetBackdrop'); 25 26 const isDesktop = () => window.matchMedia('(min-width: 768px)').matches; 26 27 28 + // function to update backdrop 29 + const updateBackdrop = () => { 30 + if (backdrop) { 31 + if (details.open && !isDesktop()) { 32 + backdrop.classList.remove('opacity-0', 'pointer-events-none'); 33 + backdrop.classList.add('opacity-100', 'pointer-events-auto'); 34 + document.body.style.overflow = 'hidden'; 35 + } else { 36 + backdrop.classList.remove('opacity-100', 'pointer-events-auto'); 37 + backdrop.classList.add('opacity-0', 'pointer-events-none'); 38 + document.body.style.overflow = ''; 39 + } 40 + } 41 + }; 42 + 27 43 // close on mobile initially 28 44 if (!isDesktop()) { 29 45 details.open = false; 30 46 } 47 + updateBackdrop(); // initialize backdrop 31 48 32 49 // prevent closing on desktop 33 50 details.addEventListener('toggle', function(e) { 34 51 if (isDesktop() && !this.open) { 35 52 this.open = true; 36 53 } 54 + updateBackdrop(); 37 55 }); 38 56 39 57 const mediaQuery = window.matchMedia('(min-width: 768px)'); ··· 45 63 // switched to mobile - close 46 64 details.open = false; 47 65 } 66 + updateBackdrop(); 48 67 }); 68 + 69 + // close when clicking backdrop 70 + if (backdrop) { 71 + backdrop.addEventListener('click', () => { 72 + if (!isDesktop()) { 73 + details.open = false; 74 + } 75 + }); 76 + } 49 77 })(); 50 78 </script> 51 79 {{ end }} ··· 109 137 {{ define "subsPanel" }} 110 138 {{ $root := index . 2 }} 111 139 {{ $pull := $root.Pull }} 112 - 113 140 <!-- backdrop overlay - only visible on mobile when open --> 114 - <div class=" 115 - fixed inset-0 bg-black/50 z-50 md:hidden opacity-0 116 - pointer-events-none transition-opacity duration-300 117 - has-[~#subs_details[open]]:opacity-100 has-[~#subs_details[open]]:pointer-events-auto"> 118 - </div> 141 + <div id="bottomSheetBackdrop" class="fixed inset-0 bg-black/50 md:hidden opacity-0 pointer-events-none transition-opacity duration-300 z-40"></div> 119 142 <!-- right panel - bottom sheet on mobile, side panel on desktop --> 120 143 <div id="subs" class="fixed bottom-0 left-0 right-0 z-50 w-full md:static md:z-auto md:max-h-screen md:sticky md:top-12 overflow-hidden"> 121 - <details open id="bottomSheet" class="group rounded-t-2xl md:rounded-t drop-shadow-lg md:drop-shadow-none"> 144 + <details open id="bottomSheet" class="rounded-t-2xl md:rounded-t drop-shadow-lg md:drop-shadow-none group/panel"> 122 145 <summary class=" 123 146 flex gap-4 items-center justify-between 124 147 rounded-t-2xl md:rounded-t cursor-pointer list-none p-4 md:h-12 ··· 127 150 md:bg-white md:dark:bg-gray-800 128 151 drop-shadow-sm 129 152 border-t md:border-x md:border-t-0 border-gray-200 dark:border-gray-700"> 130 - <h2 class="">Submissions</h2> 153 + <h2 class="">History</h2> 131 154 {{ template "subsPanelSummary" $ }} 132 155 </summary> 133 156 <div class="max-h-[85vh] md:max-h-[calc(100vh-3rem-3rem)] w-full flex flex-col-reverse gap-4 overflow-y-auto bg-slate-100 dark:bg-gray-900 md:bg-transparent"> ··· 140 163 {{ define "subsPanelSummary" }} 141 164 {{ $root := index . 2 }} 142 165 {{ $pull := $root.Pull }} 143 - {{ $latest := $pull.LastRoundNumber }} 166 + {{ $rounds := len $pull.Submissions }} 167 + {{ $comments := $pull.TotalComments }} 144 168 <div class="flex items-center gap-2 text-sm"> 145 - <!--{{ if $root.IsInterdiff }} 146 - <span> 147 - viewing interdiff of 148 - <span class="font-mono">#{{ $root.ActiveRound }}</span> 149 - and 150 - <span class="font-mono">#{{ sub $root.ActiveRound 1 }}</span> 151 - </span> 152 - {{ else }} 153 - {{ if ne $root.ActiveRound $latest }} 154 - <span>(outdated)</span> 155 - <span class="before:content-['ยท']"></span> 156 - <a class="underline" href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ $latest }}?{{ safeUrl $root.DiffOpts.Encode }}"> 157 - view latest 158 - </a> 159 - {{ end }} 160 - {{ end }}--> 169 + <span> 170 + {{ $rounds }} round{{ if ne $rounds 1 }}s{{ end }} 171 + </span> 172 + <span class="select-none before:content-['\00B7']"></span> 173 + <span> 174 + {{ $comments }} comment{{ if ne $comments 1 }}s{{ end }} 175 + </span> 176 + 161 177 <span class="md:hidden inline"> 162 178 <span class="inline group-open:hidden">{{ i "chevron-up" "size-4" }}</span> 163 179 <span class="hidden group-open:inline">{{ i "chevron-down" "size-4" }}</span> ··· 217 233 {{ $idx := index . 1 }} 218 234 {{ $lastIdx := index . 2 }} 219 235 {{ $root := index . 3 }} 220 - <div class="{{ if eq $item.RoundNumber 0 }}rounded-b border-t-0{{ else }}rounded{{ end }} border border-gray-200 dark:border-gray-700 w-full shadow-sm bg-gray-50 dark:bg-gray-800/50"> 236 + {{ $round := $item.RoundNumber }} 237 + <div class=" 238 + w-full shadow-sm bg-gray-50 dark:bg-gray-900 border-2 border-t-0 239 + {{ if eq $round 0 }}rounded-b{{ else }}rounded{{ end }} 240 + {{ if eq $round $root.ActiveRound }} 241 + border-blue-200 dark:border-blue-700 242 + {{ else }} 243 + border-gray-200 dark:border-gray-700 244 + {{ end }} 245 + "> 221 246 {{ template "submissionHeader" $ }} 222 247 {{ template "submissionComments" $ }} 223 - 224 - {{ if eq $lastIdx $item.RoundNumber }} 225 - {{ block "mergeStatus" $root }} {{ end }} 226 - {{ block "resubmitStatus" $root }} {{ end }} 227 - {{ end }} 228 - 229 - {{ if $root.LoggedInUser }} 230 - {{ template "repo/pulls/fragments/pullActions" 231 - (dict 232 - "LoggedInUser" $root.LoggedInUser 233 - "Pull" $root.Pull 234 - "RepoInfo" $root.RepoInfo 235 - "RoundNumber" $item.RoundNumber 236 - "MergeCheck" $root.MergeCheck 237 - "ResubmitCheck" $root.ResubmitCheck 238 - "BranchDeleteStatus" $root.BranchDeleteStatus 239 - "Stack" $root.Stack) }} 240 - {{ end }} 241 248 </div> 242 249 {{ end }} 243 250 ··· 249 256 <div class=" 250 257 {{ if eq $round 0 }}rounded-b{{ else }}rounded{{ end }} 251 258 px-6 py-4 pr-2 pt-2 252 - {{ if eq $root.ActiveRound $round }} 253 - bg-blue-100 dark:bg-blue-900 border-b border-blue-200 dark:border-blue-700 259 + bg-white dark:bg-gray-800 260 + {{ if eq $round $root.ActiveRound }} 261 + border-t-2 border-blue-200 dark:border-blue-700 254 262 {{ else }} 255 - bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 263 + border-b-2 border-gray-200 dark:border-gray-700 256 264 {{ end }} 257 265 flex gap-2 sticky top-0 z-20"> 258 266 <!-- left column: just profile picture --> ··· 282 290 {{ $round := $item.RoundNumber }} 283 291 <div class="flex gap-2 items-center justify-between mb-1"> 284 292 <span class="inline-flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400 pt-2"> 285 - {{ resolve $root.Pull.OwnerDid }} submitted 286 - <span class="px-2 py-0.5 {{ if eq $root.ActiveRound $round }}text-white bg-blue-600 dark:bg-blue-500 border-blue-700 dark:border-blue-600{{ else }}text-black dark:text-white bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600{{ end }} rounded font-mono text-xs border"> 293 + {{ $handle := resolve $root.Pull.OwnerDid }} 294 + <a class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" href="/{{ $handle }}">{{ $handle }}</a> 295 + submitted 296 + <span class="px-2 py-0.5 text-black dark:text-white bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600 rounded font-mono text-xs border"> 287 297 #{{ $round }} 288 298 </span> 289 299 <span class="select-none before:content-['\00B7']"></span> ··· 505 515 506 516 {{ define "submissionComments" }} 507 517 {{ $item := index . 0 }} 508 - <div class="relative ml-10 border-l-2 border-gray-200 dark:border-gray-700"> 509 - {{ range $item.Comments }} 510 - {{ template "submissionComment" . }} 511 - {{ end }} 512 - </div> 518 + {{ $idx := index . 1 }} 519 + {{ $lastIdx := index . 2 }} 520 + {{ $root := index . 3 }} 521 + {{ $round := $item.RoundNumber }} 522 + {{ $c := len $item.Comments }} 523 + <details class="relative ml-10 group/comments" {{ if or (eq $c 0) (eq $root.ActiveRound $round) }}open{{ end }}> 524 + <summary class="cursor-pointer list-none"> 525 + <div class="hidden group-open/comments:block absolute -left-8 top-0 bottom-0 w-16 transition-colors flex items-center justify-center group/border z-4"> 526 + <div class="absolute left-1/2 -translate-x-1/2 top-0 bottom-0 w-0.5 group-open/comments:bg-gray-200 dark:group-open/comments:bg-gray-700 group-hover/border:bg-gray-400 dark:group-hover/border:bg-gray-500 transition-colors"> </div> 527 + </div> 528 + <div class="group-open/comments:hidden block relative group/summary py-4"> 529 + <div class="absolute -left-8 top-0 bottom-0 w-16 transition-colors flex items-center justify-center z-4"> 530 + <div class="absolute left-1/2 -translate-x-1/2 h-1/3 top-0 bottom-0 w-0.5 bg-gray-200 dark:bg-gray-700 group-hover/summary:bg-gray-400 dark:group-hover/summary:bg-gray-500 transition-colors"></div> 531 + </div> 532 + <span class="text-gray-500 dark:text-gray-400 text-sm group-hover/summary:text-gray-600 dark:group-hover/summary:text-gray-300 transition-colors flex items-center gap-2 -ml-2 relative"> 533 + {{ i "circle-plus" "size-4 z-5" }} 534 + expand {{ $c }} comment{{ if ne $c 1 }}s{{ end }} 535 + </span> 536 + </div> 537 + </summary> 538 + <div> 539 + {{ range $item.Comments }} 540 + {{ template "submissionComment" . }} 541 + {{ end }} 542 + </div> 543 + 544 + <div class="relative -ml-10"> 545 + {{ if eq $lastIdx $item.RoundNumber }} 546 + {{ block "mergeStatus" $root }} {{ end }} 547 + {{ block "resubmitStatus" $root }} {{ end }} 548 + {{ end }} 549 + </div> 550 + <div class="relative -ml-10 bg-gray-50 dark:bg-gray-900"> 551 + {{ if $root.LoggedInUser }} 552 + {{ template "repo/pulls/fragments/pullActions" 553 + (dict 554 + "LoggedInUser" $root.LoggedInUser 555 + "Pull" $root.Pull 556 + "RepoInfo" $root.RepoInfo 557 + "RoundNumber" $item.RoundNumber 558 + "MergeCheck" $root.MergeCheck 559 + "ResubmitCheck" $root.ResubmitCheck 560 + "BranchDeleteStatus" $root.BranchDeleteStatus 561 + "Stack" $root.Stack) }} 562 + {{ end }} 563 + </div> 564 + </details> 513 565 {{ end }} 514 566 515 567 {{ define "submissionComment" }} 516 568 <div id="comment-{{.ID}}" class="flex gap-2 -ml-4 py-4 w-full mx-auto"> 517 569 <!-- left column: profile picture --> 518 - <div class="flex-shrink-0"> 570 + <div class="flex-shrink-0 h-fit relative"> 519 571 <img 520 572 src="{{ tinyAvatar .OwnerDid }}" 521 573 alt="" 522 - class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900" 574 + class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900 z-5" 523 575 /> 524 576 </div> 525 577 <!-- right column: name and body in two rows --> 526 578 <div class="flex-1 min-w-0"> 527 579 <!-- Row 1: Author and timestamp --> 528 580 <div class="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-1"> 529 - <span>{{ resolve .OwnerDid }}</span> 581 + {{ $handle := resolve .OwnerDid }} 582 + <a class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" href="/{{ $handle }}">{{ $handle }}</a> 530 583 <span class="before:content-['ยท']"></span> 531 584 <a class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" href="#comment-{{.ID}}"> 532 - {{ template "repo/fragments/time" .Created }} 585 + {{ template "repo/fragments/shortTime" .Created }} 533 586 </a> 534 587 </div> 535 588 <!-- Row 2: Body text -->
+1 -1
appview/pages/templates/repo/pulls/pulls.html
··· 166 166 "Page" .Page 167 167 "TotalCount" .PullCount 168 168 "BasePath" (printf "/%s/pulls" .RepoInfo.FullName) 169 - "QueryParams" (printf "state=%s&q=%s" .FilteringBy.String .FilterQuery) 169 + "QueryParams" (queryParams "state" .FilteringBy.String "q" .FilterQuery) 170 170 ) }} 171 171 {{ end }} 172 172 {{ end }}
+1 -2
appview/pages/templates/repo/settings/fragments/sidebar.html
··· 1 1 {{ define "repo/settings/fragments/sidebar" }} 2 2 {{ $active := .Tab }} 3 - {{ $tabs := .Tabs }} 4 3 <div class="sticky top-2 grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 shadow-inner"> 5 4 {{ $activeTab := "bg-white dark:bg-gray-700 drop-shadow-sm" }} 6 5 {{ $inactiveTab := "bg-gray-100 dark:bg-gray-800" }} 7 - {{ range $tabs }} 6 + {{ range const.RepoSettingsTabs }} 8 7 <a href="/{{ $.RepoInfo.FullName }}/settings?tab={{.Name}}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25"> 9 8 <div class="flex gap-3 items-center p-2 {{ if eq .Name $active }} {{ $activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}"> 10 9 {{ i .Icon "size-4" }}
+53
appview/pages/templates/user/fragments/editAvatar.html
··· 1 + {{ define "user/fragments/editAvatar" }} 2 + <form 3 + hx-post="/profile/avatar" 4 + hx-encoding="multipart/form-data" 5 + hx-indicator="#spinner" 6 + hx-swap="none" 7 + class="flex flex-col gap-2"> 8 + <label for="avatar-file" class="uppercase p-0"> 9 + Upload or Remove Avatar 10 + </label> 11 + <p class="text-sm text-gray-500 dark:text-gray-400">Upload a new image (PNG or JPEG, max 1MB) or remove your current avatar.</p> 12 + <input 13 + type="file" 14 + id="avatar-file" 15 + name="avatar" 16 + accept="image/png,image/jpeg" 17 + required 18 + class="block w-full text-sm text-gray-500 dark:text-gray-400 19 + file:mr-4 file:py-2 file:px-4 20 + file:rounded file:border-0 21 + file:text-sm file:font-semibold 22 + file:bg-gray-100 file:text-gray-700 23 + dark:file:bg-gray-700 dark:file:text-gray-300 24 + hover:file:bg-gray-200 dark:hover:file:bg-gray-600" /> 25 + <div id="avatar-error" class="text-red-500 dark:text-red-400 text-sm min-h-5"></div> 26 + <div class="flex flex-col gap-2 pt-2"> 27 + <button type="submit" class="btn w-full flex items-center justify-center gap-2"> 28 + <span class="inline-flex gap-2 items-center">{{ i "upload" "size-4" }} upload</span> 29 + <span id="spinner" class="group"> 30 + {{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 31 + </span> 32 + </button> 33 + <button 34 + type="button" 35 + hx-delete="/profile/avatar" 36 + hx-confirm="Are you sure you want to remove your profile picture?" 37 + hx-swap="none" 38 + class="btn w-full flex items-center justify-center gap-2"> 39 + {{ i "trash-2" "size-4" }} 40 + remove avatar 41 + </button> 42 + <button 43 + id="cancel-avatar-btn" 44 + type="button" 45 + popovertarget="avatar-upload-modal" 46 + popovertargetaction="hide" 47 + class="btn w-full flex items-center justify-center gap-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"> 48 + {{ i "x" "size-4" }} 49 + cancel 50 + </button> 51 + </div> 52 + </form> 53 + {{ end }}
+39 -22
appview/pages/templates/user/fragments/profileCard.html
··· 3 3 <div class="grid grid-cols-3 md:grid-cols-1 gap-1 items-center"> 4 4 <div id="avatar" class="col-span-1 flex justify-center items-center"> 5 5 <div class="w-3/4 aspect-square relative"> 6 - <img class="absolute inset-0 w-full h-full object-cover rounded-full p-2" src="{{ fullAvatar .UserDid }}" /> 6 + <img class="absolute inset-0 w-full h-full object-cover rounded-full p-2" src="{{ profileAvatarUrl .Profile "" }}" /> 7 + {{ if eq .FollowStatus.String "IsSelf" }} 8 + <button 9 + class="absolute bottom-2 right-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-full p-2 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors" 10 + popovertarget="avatar-upload-modal" 11 + popovertargetaction="toggle" 12 + title="Upload avatar"> 13 + {{ i "camera" "w-4 h-4" }} 14 + </button> 15 + {{ end }} 7 16 </div> 8 17 </div> 18 + <div 19 + id="avatar-upload-modal" 20 + popover 21 + class="bg-white w-full md:w-96 dark:bg-gray-800 p-4 rounded border border-gray-200 dark:border-gray-700 drop-shadow dark:text-white backdrop:bg-gray-400/50 dark:backdrop:bg-gray-800/50"> 22 + {{ template "user/fragments/editAvatar" . }} 23 + </div> 9 24 <div class="col-span-2"> 10 25 <div class="flex items-center flex-row flex-nowrap gap-2"> 11 26 <p title="{{ $userIdent }}" ··· 13 28 {{ $userIdent }} 14 29 </p> 15 30 {{ with .Profile }} 16 - {{ if .Pronouns }} 17 - <p class="text-gray-500 dark:text-gray-400">{{ .Pronouns }}</p> 18 - {{ end }} 31 + {{ if .Pronouns }} 32 + <p class="text-gray-500 dark:text-gray-400">{{ .Pronouns }}</p> 33 + {{ end }} 19 34 {{ end }} 20 35 </div> 21 36 ··· 29 44 {{ with .Profile }} 30 45 31 46 {{ if .Description }} 32 - <p class="text-base pb-4 md:pb-2">{{ .Description }}</p> 47 + <p class="text-base pb-4 md:pb-2">{{ .Description }}</p> 33 48 {{ end }} 34 49 35 50 <div class="hidden md:block"> ··· 45 60 {{ end }} 46 61 {{ if .IncludeBluesky }} 47 62 <div class="flex items-center gap-2"> 48 - <span class="flex-shrink-0">{{ template "user/fragments/bluesky" "w-4 h-4 text-black dark:text-white" 49 - }}</span> 63 + <span class="flex-shrink-0">{{ template "user/fragments/bluesky" "w-4 h-4 text-black dark:text-white" }}</span> 50 64 <a id="bluesky-link" href="https://bsky.app/profile/{{ $.UserDid }}">{{ $userIdent }}</a> 51 65 </div> 52 66 {{ end }} 53 67 {{ range $link := .Links }} 54 - {{ if $link }} 55 - <div class="flex items-center gap-2"> 56 - <span class="flex-shrink-0">{{ i "link" "size-4" }}</span> 57 - <a href="{{ $link }}">{{ $link }}</a> 58 - </div> 59 - {{ end }} 68 + {{ if $link }} 69 + <div class="flex items-center gap-2"> 70 + <span class="flex-shrink-0">{{ i "link" "size-4" }}</span> 71 + <a href="{{ $link }}">{{ $link }}</a> 72 + </div> 73 + {{ end }} 60 74 {{ end }} 61 75 {{ if not $profile.IsStatsEmpty }} 62 76 <div class="flex items-center justify-evenly gap-2 py-2"> 63 77 {{ range $stat := .Stats }} 64 - {{ if $stat.Kind }} 65 - <div class="flex flex-col items-center gap-2"> 66 - <span class="text-xl font-bold">{{ $stat.Value }}</span> 67 - <span>{{ $stat.Kind.String }}</span> 68 - </div> 69 - {{ end }} 78 + {{ if $stat.Kind }} 79 + <div class="flex flex-col items-center gap-2"> 80 + <span class="text-xl font-bold">{{ $stat.Value }}</span> 81 + <span>{{ $stat.Kind.String }}</span> 82 + </div> 83 + {{ end }} 70 84 {{ end }} 71 85 </div> 72 86 {{ end }} ··· 75 89 76 90 <div class="flex mt-2 items-center gap-2"> 77 91 {{ if ne .FollowStatus.String "IsSelf" }} 78 - {{ template "user/fragments/follow" . }} 92 + {{ template "user/fragments/follow" . }} 79 93 {{ else }} 80 - <button id="editBtn" class="btn w-full flex items-center gap-2 group" hx-target="#profile-bio" 81 - hx-get="/profile/edit-bio" hx-swap="innerHTML"> 94 + <button id="editBtn" 95 + class="btn w-full flex items-center gap-2 group" 96 + hx-target="#profile-bio" 97 + hx-get="/profile/edit-bio" 98 + hx-swap="innerHTML"> 82 99 {{ i "pencil" "w-4 h-4" }} 83 100 edit 84 101 {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+4 -2
appview/pages/templates/user/settings/emails.html
··· 62 62 hx-swap="none" 63 63 class="flex flex-col gap-2" 64 64 > 65 - <p class="uppercase p-0">ADD EMAIL</p> 65 + <label for="email-address" class="uppercase p-0"> 66 + add email 67 + </label> 66 68 <p class="text-sm text-gray-500 dark:text-gray-400">Commits using this email will be associated with your profile.</p> 67 69 <input 68 70 type="email" ··· 91 93 <div id="settings-emails-error" class="text-red-500 dark:text-red-400"></div> 92 94 <div id="settings-emails-success" class="text-green-500 dark:text-green-400"></div> 93 95 </form> 94 - {{ end }} 96 + {{ end }}
+2 -3
appview/pages/templates/user/settings/fragments/sidebar.html
··· 1 1 {{ define "user/settings/fragments/sidebar" }} 2 2 {{ $active := .Tab }} 3 - {{ $tabs := .Tabs }} 4 3 <div class="sticky top-2 grid grid-cols-1 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 shadow-inner"> 5 4 {{ $activeTab := "bg-white dark:bg-gray-700 drop-shadow-sm" }} 6 5 {{ $inactiveTab := "bg-gray-100 dark:bg-gray-800" }} 7 - {{ range $tabs }} 6 + {{ range const.UserSettingsTabs }} 8 7 <a href="/settings/{{.Name}}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25"> 9 8 <div class="flex gap-3 items-center p-2 {{ if eq .Name $active }} {{ $activeTab }} {{ else }} {{ $inactiveTab }} {{ end }}"> 10 9 {{ i .Icon "size-4" }} ··· 13 12 </a> 14 13 {{ end }} 15 14 </div> 16 - {{ end }} 15 + {{ end }}
+4 -2
appview/pages/templates/user/settings/keys.html
··· 21 21 <div class="col-span-1 md:col-span-2"> 22 22 <h2 class="text-sm pb-2 uppercase font-bold">SSH Keys</h2> 23 23 <p class="text-gray-500 dark:text-gray-400"> 24 - SSH public keys added here will be broadcasted to knots that you are a member of, 24 + SSH public keys added here will be broadcasted to knots that you are a member of, 25 25 allowing you to push to repositories there. 26 26 </p> 27 27 </div> ··· 63 63 hx-swap="none" 64 64 class="flex flex-col gap-2" 65 65 > 66 - <p class="uppercase p-0">ADD SSH KEY</p> 66 + <label for="key-name" class="uppercase p-0"> 67 + add ssh key 68 + </label> 67 69 <p class="text-sm text-gray-500 dark:text-gray-400">SSH keys allow you to push to repositories in knots you're a member of.</p> 68 70 <input 69 71 type="text"
-31
appview/pages/templates/user/settings/profile.html
··· 59 59 </div> 60 60 </div> 61 61 </div> 62 - <div class="flex flex-col rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700 w-full"> 63 - <div class="flex items-center justify-between p-4"> 64 - <div class="hover:no-underline flex flex-col gap-1 min-w-0 max-w-[80%]"> 65 - <div class="flex flex-wrap text-sm items-center gap-1 text-gray-500 dark:text-gray-400"> 66 - <span>Punchcard settings</span> 67 - </div> 68 - <form hx-post="/profile/punchcard" class="col-span-1 md:col-span-1 md:justify-self-end group flex gap-2 items-stretch"> 69 - <select 70 - id="punchcard-setting" 71 - name="punchcard-setting" 72 - required 73 - class="p-1 max-w-64 border border-gray-200 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700"> 74 - {{/* For some reason, we can't use an empty string in a <select> in all scenarios unless it is preceded by a disabled select?? No idea, could just be a Firefox thing? */}} 75 - <option value="[[none]]" class="py-1" {{ if not $.PunchcardSetting }}selected{{ end }}> 76 - Show all 77 - </option> 78 - <option value="HIDE_MINE" class="py-1" {{ if eq "HIDE_MINE" $.PunchcardSetting }}selected{{ end }}> 79 - Hide mine for others 80 - </option> 81 - <option value="HIDE_ALL" class="py-1" {{ if eq "HIDE_ALL" $.PunchcardSetting }}selected{{ end }}> 82 - Hide everyones for me 83 - </option> 84 - </select> 85 - <button class="btn flex gap-2 items-center" type="submit"> 86 - {{ i "check" "size-4" }} 87 - {{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 88 - </button> 89 - </form> 90 - </div> 91 - </div> 92 - </div> 93 62 {{ end }}
+10 -4
appview/pulls/pulls.go
··· 289 289 ActiveRound: roundIdInt, 290 290 IsInterdiff: interdiff, 291 291 292 - OrderedReactionKinds: models.OrderedReactionKinds, 293 - Reactions: reactionMap, 294 - UserReacted: userReactions, 292 + Reactions: reactionMap, 293 + UserReacted: userReactions, 295 294 296 295 LabelDefs: defs, 297 296 }) 298 297 } 299 298 300 299 func (s *Pulls) RepoSinglePull(w http.ResponseWriter, r *http.Request) { 301 - s.repoPullHelper(w, r, false) 300 + pull, ok := r.Context().Value("pull").(*models.Pull) 301 + if !ok { 302 + log.Println("failed to get pull") 303 + s.pages.Notice(w, "pull-error", "Failed to edit patch. Try again later.") 304 + return 305 + } 306 + 307 + http.Redirect(w, r, r.URL.String()+fmt.Sprintf("/round/%d", pull.LastRoundNumber()), http.StatusFound) 302 308 } 303 309 304 310 func (s *Pulls) mergeCheck(r *http.Request, f *models.Repo, pull *models.Pull, stack models.Stack) types.MergeCheckResponse {
+17 -2
appview/repo/blob.go
··· 219 219 if resp.Content != nil { 220 220 bytes, _ := base64.StdEncoding.DecodeString(*resp.Content) 221 221 view.Contents = string(bytes) 222 - view.Lines = strings.Count(view.Contents, "\n") + 1 222 + view.Lines = countLines(view.Contents) 223 223 } 224 224 225 225 case ".mp4", ".webm", ".ogg", ".mov", ".avi": ··· 238 238 239 239 if resp.Content != nil { 240 240 view.Contents = *resp.Content 241 - view.Lines = strings.Count(view.Contents, "\n") + 1 241 + view.Lines = countLines(view.Contents) 242 242 } 243 243 244 244 // with text, we may be dealing with markdown ··· 291 291 } 292 292 return slices.Contains(textualTypes, mimeType) 293 293 } 294 + 295 + // TODO: dedup with strings 296 + func countLines(content string) int { 297 + if content == "" { 298 + return 0 299 + } 300 + 301 + count := strings.Count(content, "\n") 302 + 303 + if !strings.HasSuffix(content, "\n") { 304 + count++ 305 + } 306 + 307 + return count 308 + }
+10
appview/repo/repo.go
··· 1004 1004 return 1005 1005 } 1006 1006 1007 + defaultKnot := "" 1008 + knotPrefence, err := db.GetKnotPreference(rp.db, user.Did()) 1009 + if err != nil { 1010 + rp.logger.Warn("gettings users knot preferences", "error", err) 1011 + } 1012 + if knotPrefence != nil { 1013 + defaultKnot = knotPrefence.DefaultKnot 1014 + } 1015 + 1007 1016 rp.pages.ForkRepo(w, pages.ForkRepoParams{ 1008 1017 LoggedInUser: user, 1009 1018 Knots: knots, 1010 1019 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 1020 + DefaultKnot: defaultKnot, 1011 1021 }) 1012 1022 1013 1023 case http.MethodPost:
-17
appview/repo/settings.go
··· 22 22 indigoxrpc "github.com/bluesky-social/indigo/xrpc" 23 23 ) 24 24 25 - type tab = map[string]any 26 - 27 - var ( 28 - // would be great to have ordered maps right about now 29 - settingsTabs []tab = []tab{ 30 - {"Name": "general", "Icon": "sliders-horizontal"}, 31 - {"Name": "access", "Icon": "users"}, 32 - {"Name": "pipelines", "Icon": "layers-2"}, 33 - } 34 - ) 35 - 36 25 func (rp *Repo) SetDefaultBranch(w http.ResponseWriter, r *http.Request) { 37 26 l := rp.logger.With("handler", "SetDefaultBranch") 38 27 ··· 262 251 DefaultLabels: defaultLabels, 263 252 SubscribedLabels: subscribedLabels, 264 253 ShouldSubscribeAll: shouldSubscribeAll, 265 - Tabs: settingsTabs, 266 - Tab: "general", 267 254 }) 268 255 } 269 256 ··· 308 295 rp.pages.RepoAccessSettings(w, pages.RepoAccessSettingsParams{ 309 296 LoggedInUser: user, 310 297 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 311 - Tabs: settingsTabs, 312 - Tab: "access", 313 298 Collaborators: collaborators, 314 299 }) 315 300 } ··· 369 354 rp.pages.RepoPipelineSettings(w, pages.RepoPipelineSettingsParams{ 370 355 LoggedInUser: user, 371 356 RepoInfo: rp.repoResolver.GetRepoInfo(r, user), 372 - Tabs: settingsTabs, 373 - Tab: "pipelines", 374 357 Spindles: spindles, 375 358 CurrentSpindle: f.Spindle, 376 359 Secrets: niceSecret,
+2 -32
appview/settings/settings.go
··· 35 35 Config *config.Config 36 36 } 37 37 38 - type tab = map[string]any 39 - 40 - var ( 41 - settingsTabs []tab = []tab{ 42 - {"Name": "profile", "Icon": "user"}, 43 - {"Name": "keys", "Icon": "key"}, 44 - {"Name": "emails", "Icon": "mail"}, 45 - {"Name": "notifications", "Icon": "bell"}, 46 - {"Name": "knots", "Icon": "volleyball"}, 47 - {"Name": "spindles", "Icon": "spool"}, 48 - } 49 - ) 50 - 51 38 func (s *Settings) Router() http.Handler { 52 39 r := chi.NewRouter() 53 40 ··· 82 69 83 70 func (s *Settings) profileSettings(w http.ResponseWriter, r *http.Request) { 84 71 user := s.OAuth.GetMultiAccountUser(r) 85 - profile, err := db.GetProfile(s.Db, user.Did()) 86 - if err != nil { 87 - log.Printf("failed to get profile to check punchcard settings: %s", err) 88 - } 89 72 90 - params := pages.UserProfileSettingsParams{ 73 + s.Pages.UserProfileSettings(w, pages.UserProfileSettingsParams{ 91 74 LoggedInUser: user, 92 - Tabs: settingsTabs, 93 - Tab: "profile", 94 - } 95 - if profile != nil { 96 - params.PunchcardSetting = profile.PunchardSetting 97 - } 98 - 99 - s.Pages.UserProfileSettings(w, params) 75 + }) 100 76 } 101 77 102 78 func (s *Settings) notificationsSettings(w http.ResponseWriter, r *http.Request) { ··· 113 89 s.Pages.UserNotificationSettings(w, pages.UserNotificationSettingsParams{ 114 90 LoggedInUser: user, 115 91 Preferences: prefs, 116 - Tabs: settingsTabs, 117 - Tab: "notifications", 118 92 }) 119 93 } 120 94 ··· 155 129 s.Pages.UserKeysSettings(w, pages.UserKeysSettingsParams{ 156 130 LoggedInUser: user, 157 131 PubKeys: pubKeys, 158 - Tabs: settingsTabs, 159 - Tab: "keys", 160 132 }) 161 133 } 162 134 ··· 170 142 s.Pages.UserEmailsSettings(w, pages.UserEmailsSettingsParams{ 171 143 LoggedInUser: user, 172 144 Emails: emails, 173 - Tabs: settingsTabs, 174 - Tab: "emails", 175 145 }) 176 146 } 177 147
-15
appview/spindles/spindles.go
··· 39 39 Logger *slog.Logger 40 40 } 41 41 42 - type tab = map[string]any 43 - 44 - var ( 45 - spindlesTabs []tab = []tab{ 46 - {"Name": "profile", "Icon": "user"}, 47 - {"Name": "keys", "Icon": "key"}, 48 - {"Name": "emails", "Icon": "mail"}, 49 - {"Name": "notifications", "Icon": "bell"}, 50 - {"Name": "knots", "Icon": "volleyball"}, 51 - {"Name": "spindles", "Icon": "spool"}, 52 - } 53 - ) 54 - 55 42 func (s *Spindles) Router() http.Handler { 56 43 r := chi.NewRouter() 57 44 ··· 83 70 s.Pages.Spindles(w, pages.SpindlesParams{ 84 71 LoggedInUser: user, 85 72 Spindles: all, 86 - Tabs: spindlesTabs, 87 73 Tab: "spindles", 88 74 }) 89 75 } ··· 143 129 Spindle: spindle, 144 130 Members: members, 145 131 Repos: repoMap, 146 - Tabs: spindlesTabs, 147 132 Tab: "spindles", 148 133 }) 149 134 }
+198 -42
appview/state/profile.go
··· 157 157 } 158 158 } 159 159 160 - loggedInUser := s.oauth.GetMultiAccountUser(r) 161 - 162 - forProfile, err := db.GetProfile(s.db, profile.UserDid) 163 - if err != nil { 164 - l.Error("failed to get for profile to check punchcard settings", "err", err) 165 - } 166 - requesterProfile, err := db.GetProfile(s.db, loggedInUser.Did()) 167 - if err != nil { 168 - l.Error("failed to get requester profile to check punchcard settings", "err", err) 169 - } 170 - 171 - showPunchcard := true 172 - if forProfile != nil && forProfile.PunchardSetting == models.ProfilePunchcardOptionHideMine { 173 - showPunchcard = false 174 - } 175 - if requesterProfile != nil && requesterProfile.PunchardSetting == models.ProfilePunchcardOptionHideAll { 176 - showPunchcard = false 177 - } 178 - 179 - timeline, err := db.MakeProfileTimeline(s.db, profile.UserDid, showPunchcard) 160 + timeline, err := db.MakeProfileTimeline(s.db, profile.UserDid) 180 161 if err != nil { 181 162 l.Error("failed to create timeline", "err", err) 182 - } 183 - 184 - loggedInUserProfile, err := db.GetProfile(s.db, loggedInUser.Did()) 185 - if err != nil { 186 - l.Error("failed to get logged in user profile to check punchcard settings", "err", err) 187 - } 188 - 189 - if loggedInUserProfile != nil && loggedInUserProfile.PunchardSetting == models.ProfilePunchcardOptionHideAll { 190 - 191 163 } 192 164 193 165 s.pages.ProfileOverview(w, pages.ProfileOverviewParams{ 194 - LoggedInUser: loggedInUser, 166 + LoggedInUser: s.oauth.GetMultiAccountUser(r), 195 167 Card: profile, 196 168 Repos: pinnedRepos, 197 169 CollaboratingRepos: pinnedCollaboratingRepos, 198 170 ProfileTimeline: timeline, 199 - ShowPunchcard: showPunchcard, 200 171 }) 201 172 } 202 173 ··· 433 404 } 434 405 435 406 func (s *State) getProfileFeed(ctx context.Context, id *identity.Identity) (*feeds.Feed, error) { 436 - timeline, err := db.MakeProfileTimeline(s.db, id.DID.String(), false) 407 + timeline, err := db.MakeProfileTimeline(s.db, id.DID.String()) 437 408 if err != nil { 438 409 return nil, err 439 410 } ··· 634 605 s.updateProfile(profile, w, r) 635 606 } 636 607 608 + func (s *State) UpdateDefaultKnotPreference(w http.ResponseWriter, r *http.Request) { 609 + err := r.ParseForm() 610 + if err != nil { 611 + log.Println("invalid preference update form", err) 612 + return 613 + } 614 + user := s.oauth.GetMultiAccountUser(r) 615 + 616 + defaultKnot := r.Form.Get("default-knot") 617 + 618 + if defaultKnot == "[[none]]" { // see pages/templates/knots/index.html for more info on why we use this value 619 + defaultKnot = "" 620 + } 621 + 622 + err = db.UpsertKnotPreference(s.db, user.Did(), defaultKnot) 623 + if err != nil { 624 + log.Println("failed to update default knot preference", err) 625 + return 626 + } 627 + 628 + s.pages.HxRefresh(w) 629 + } 630 + 637 631 func (s *State) updateProfile(profile *models.Profile, w http.ResponseWriter, r *http.Request) { 638 632 user := s.oauth.GetMultiAccountUser(r) 639 633 tx, err := s.db.BeginTx(r.Context(), nil) ··· 758 752 }) 759 753 } 760 754 761 - func (s *State) UpdateProfilePunchcardSetting(w http.ResponseWriter, r *http.Request) { 762 - err := r.ParseForm() 755 + func (s *State) UploadProfileAvatar(w http.ResponseWriter, r *http.Request) { 756 + l := s.logger.With("handler", "UploadProfileAvatar") 757 + user := s.oauth.GetUser(r) 758 + l = l.With("did", user.Did) 759 + 760 + // Parse multipart form (10MB max) 761 + if err := r.ParseMultipartForm(10 << 20); err != nil { 762 + l.Error("failed to parse form", "err", err) 763 + s.pages.Notice(w, "avatar-error", "Failed to parse form") 764 + return 765 + } 766 + 767 + file, handler, err := r.FormFile("avatar") 763 768 if err != nil { 764 - log.Println("invalid profile update form", err) 769 + l.Error("failed to read avatar file", "err", err) 770 + s.pages.Notice(w, "avatar-error", "Failed to read avatar file") 771 + return 772 + } 773 + defer file.Close() 774 + 775 + if handler.Size > 1000000 { 776 + l.Warn("avatar file too large", "size", handler.Size) 777 + s.pages.Notice(w, "avatar-error", "Avatar file too large (max 1MB)") 765 778 return 766 779 } 767 - user := s.oauth.GetUser(r) 780 + 781 + contentType := handler.Header.Get("Content-Type") 782 + if contentType != "image/png" && contentType != "image/jpeg" { 783 + l.Warn("invalid image type", "contentType", contentType) 784 + s.pages.Notice(w, "avatar-error", "Invalid image type (only PNG and JPEG allowed)") 785 + return 786 + } 787 + 788 + client, err := s.oauth.AuthorizedClient(r) 789 + if err != nil { 790 + l.Error("failed to get PDS client", "err", err) 791 + s.pages.Notice(w, "avatar-error", "Failed to connect to your PDS") 792 + return 793 + } 794 + 795 + uploadBlobResp, err := comatproto.RepoUploadBlob(r.Context(), client, file) 796 + if err != nil { 797 + l.Error("failed to upload avatar blob", "err", err) 798 + s.pages.Notice(w, "avatar-error", "Failed to upload avatar to your PDS") 799 + return 800 + } 801 + 802 + l.Info("uploaded avatar blob", "cid", uploadBlobResp.Blob.Ref.String()) 803 + 804 + // get current profile record from PDS to get its CID for swap 805 + getRecordResp, err := comatproto.RepoGetRecord(r.Context(), client, "", tangled.ActorProfileNSID, user.Did, "self") 806 + if err != nil { 807 + l.Error("failed to get current profile record", "err", err) 808 + s.pages.Notice(w, "avatar-error", "Failed to get current profile from your PDS") 809 + return 810 + } 811 + 812 + var profileRecord *tangled.ActorProfile 813 + if getRecordResp.Value != nil { 814 + if val, ok := getRecordResp.Value.Val.(*tangled.ActorProfile); ok { 815 + profileRecord = val 816 + } else { 817 + l.Warn("profile record type assertion failed, creating new record") 818 + profileRecord = &tangled.ActorProfile{} 819 + } 820 + } else { 821 + l.Warn("no existing profile record, creating new record") 822 + profileRecord = &tangled.ActorProfile{} 823 + } 824 + 825 + profileRecord.Avatar = uploadBlobResp.Blob 826 + 827 + _, err = comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 828 + Collection: tangled.ActorProfileNSID, 829 + Repo: user.Did, 830 + Rkey: "self", 831 + Record: &lexutil.LexiconTypeDecoder{Val: profileRecord}, 832 + SwapRecord: getRecordResp.Cid, 833 + }) 834 + 835 + if err != nil { 836 + l.Error("failed to update profile record", "err", err) 837 + s.pages.Notice(w, "avatar-error", "Failed to update profile on your PDS") 838 + return 839 + } 840 + 841 + l.Info("successfully updated profile with avatar") 768 842 769 843 profile, err := db.GetProfile(s.db, user.Did) 770 844 if err != nil { 771 - log.Printf("getting profile data for %s: %s", user.Did, err) 845 + l.Warn("getting profile data from DB", "err", err) 846 + profile = &models.Profile{Did: user.Did} 772 847 } 848 + profile.Avatar = uploadBlobResp.Blob.Ref.String() 773 849 774 - if profile == nil { 850 + tx, err := s.db.BeginTx(r.Context(), nil) 851 + if err != nil { 852 + l.Error("failed to start transaction", "err", err) 853 + s.pages.HxRefresh(w) 854 + w.WriteHeader(http.StatusOK) 775 855 return 776 856 } 777 857 778 - punchcard := r.Form.Get("punchcard-setting") 858 + err = db.UpsertProfile(tx, profile) 859 + if err != nil { 860 + l.Error("failed to update profile in DB", "err", err) 861 + s.pages.HxRefresh(w) 862 + w.WriteHeader(http.StatusOK) 863 + return 864 + } 779 865 780 - err = db.SetProfilePunchcardStatus(s.db, profile.Did, models.ProfilePunchcardFromString(punchcard)) 866 + s.pages.HxRedirect(w, r.Header.Get("Referer")) 867 + } 868 + 869 + func (s *State) RemoveProfileAvatar(w http.ResponseWriter, r *http.Request) { 870 + l := s.logger.With("handler", "RemoveProfileAvatar") 871 + user := s.oauth.GetUser(r) 872 + l = l.With("did", user.Did) 873 + 874 + client, err := s.oauth.AuthorizedClient(r) 781 875 if err != nil { 782 - log.Println("failed to update profile", err) 876 + l.Error("failed to get PDS client", "err", err) 877 + s.pages.Notice(w, "avatar-error", "Failed to connect to your PDS") 783 878 return 784 879 } 785 880 786 - s.pages.HxRefresh(w) 881 + getRecordResp, err := comatproto.RepoGetRecord(r.Context(), client, "", tangled.ActorProfileNSID, user.Did, "self") 882 + if err != nil { 883 + l.Error("failed to get current profile record", "err", err) 884 + s.pages.Notice(w, "avatar-error", "Failed to get current profile from your PDS") 885 + return 886 + } 887 + 888 + var profileRecord *tangled.ActorProfile 889 + if getRecordResp.Value != nil { 890 + if val, ok := getRecordResp.Value.Val.(*tangled.ActorProfile); ok { 891 + profileRecord = val 892 + } else { 893 + l.Warn("profile record type assertion failed") 894 + profileRecord = &tangled.ActorProfile{} 895 + } 896 + } else { 897 + l.Warn("no existing profile record") 898 + profileRecord = &tangled.ActorProfile{} 899 + } 900 + 901 + profileRecord.Avatar = nil 902 + 903 + _, err = comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 904 + Collection: tangled.ActorProfileNSID, 905 + Repo: user.Did, 906 + Rkey: "self", 907 + Record: &lexutil.LexiconTypeDecoder{Val: profileRecord}, 908 + SwapRecord: getRecordResp.Cid, 909 + }) 910 + 911 + if err != nil { 912 + l.Error("failed to update profile record", "err", err) 913 + s.pages.Notice(w, "avatar-error", "Failed to remove avatar from your PDS") 914 + return 915 + } 916 + 917 + l.Info("successfully removed avatar from PDS") 918 + 919 + profile, err := db.GetProfile(s.db, user.Did) 920 + if err != nil { 921 + l.Warn("getting profile data from DB", "err", err) 922 + profile = &models.Profile{Did: user.Did} 923 + } 924 + profile.Avatar = "" 925 + 926 + tx, err := s.db.BeginTx(r.Context(), nil) 927 + if err != nil { 928 + l.Error("failed to start transaction", "err", err) 929 + s.pages.HxRefresh(w) 930 + w.WriteHeader(http.StatusOK) 931 + return 932 + } 933 + 934 + err = db.UpsertProfile(tx, profile) 935 + if err != nil { 936 + l.Error("failed to update profile in DB", "err", err) 937 + s.pages.HxRefresh(w) 938 + w.WriteHeader(http.StatusOK) 939 + return 940 + } 941 + 942 + s.pages.HxRedirect(w, r.Header.Get("Referer")) 787 943 }
+3 -1
appview/state/router.go
··· 165 165 r.Get("/edit-pins", s.EditPinsFragment) 166 166 r.Post("/bio", s.UpdateProfileBio) 167 167 r.Post("/pins", s.UpdateProfilePins) 168 - r.Post("/punchcard", s.UpdateProfilePunchcardSetting) 168 + r.Post("/avatar", s.UploadProfileAvatar) 169 + r.Delete("/avatar", s.RemoveProfileAvatar) 170 + r.Post("/default-knot", s.UpdateDefaultKnotPreference) 169 171 }) 170 172 171 173 r.Mount("/settings", s.SettingsRouter())
+11 -1
appview/state/state.go
··· 92 92 return nil, fmt.Errorf("failed to create posthog client: %w", err) 93 93 } 94 94 95 - pages := pages.NewPages(config, res, log.SubLogger(logger, "pages")) 95 + pages := pages.NewPages(config, res, d, log.SubLogger(logger, "pages")) 96 96 oauth, err := oauth.New(config, posthog, d, enforcer, res, log.SubLogger(logger, "oauth")) 97 97 if err != nil { 98 98 return nil, fmt.Errorf("failed to start oauth handler: %w", err) ··· 418 418 return 419 419 } 420 420 421 + defaultKnot := "" 422 + knotPrefence, err := db.GetKnotPreference(s.db, user.Did()) 423 + if err != nil { 424 + s.logger.Warn("gettings users knot preferences", "error", err) 425 + } 426 + if knotPrefence != nil { 427 + defaultKnot = knotPrefence.DefaultKnot 428 + } 429 + 421 430 s.pages.NewRepo(w, pages.NewRepoParams{ 422 431 LoggedInUser: user, 423 432 Knots: knots, 433 + DefaultKnot: defaultKnot, 424 434 }) 425 435 426 436 case http.MethodPost:
+3113 -3022
avatar/package-lock.json
··· 1 1 { 2 - "name": "avatar", 3 - "version": "0.0.0", 4 - "lockfileVersion": 3, 5 - "requires": true, 6 - "packages": { 7 - "": { 8 - "name": "avatar", 9 - "version": "0.0.0", 10 - "devDependencies": { 11 - "@cloudflare/vitest-pool-workers": "^0.8.19", 12 - "vitest": "~3.0.7", 13 - "wrangler": "^4.14.1" 14 - } 15 - }, 16 - "node_modules/@cloudflare/kv-asset-handler": { 17 - "version": "0.4.0", 18 - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", 19 - "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", 20 - "dev": true, 21 - "license": "MIT OR Apache-2.0", 22 - "dependencies": { 23 - "mime": "^3.0.0" 24 - }, 25 - "engines": { 26 - "node": ">=18.0.0" 27 - } 28 - }, 29 - "node_modules/@cloudflare/unenv-preset": { 30 - "version": "2.3.1", 31 - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.3.1.tgz", 32 - "integrity": "sha512-Xq57Qd+ADpt6hibcVBO0uLG9zzRgyRhfCUgBT9s+g3+3Ivg5zDyVgLFy40ES1VdNcu8rPNSivm9A+kGP5IVaPg==", 33 - "dev": true, 34 - "license": "MIT OR Apache-2.0", 35 - "peerDependencies": { 36 - "unenv": "2.0.0-rc.15", 37 - "workerd": "^1.20250320.0" 38 - }, 39 - "peerDependenciesMeta": { 40 - "workerd": { 41 - "optional": true 42 - } 43 - } 44 - }, 45 - "node_modules/@cloudflare/vitest-pool-workers": { 46 - "version": "0.8.24", 47 - "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.8.24.tgz", 48 - "integrity": "sha512-wT2PABJQ9YLYWrVu4CRZOjvmjHkdbMyLTZPU9n/7JEMM3pgG8dY41F1Rj31UsXRQaXX39A/CTPGlk58dcMUysA==", 49 - "dev": true, 50 - "license": "MIT", 51 - "dependencies": { 52 - "birpc": "0.2.14", 53 - "cjs-module-lexer": "^1.2.3", 54 - "devalue": "^4.3.0", 55 - "miniflare": "4.20250428.1", 56 - "semver": "^7.7.1", 57 - "wrangler": "4.14.1", 58 - "zod": "^3.22.3" 59 - }, 60 - "peerDependencies": { 61 - "@vitest/runner": "2.0.x - 3.1.x", 62 - "@vitest/snapshot": "2.0.x - 3.1.x", 63 - "vitest": "2.0.x - 3.1.x" 64 - } 65 - }, 66 - "node_modules/@cloudflare/workerd-darwin-64": { 67 - "version": "1.20250428.0", 68 - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250428.0.tgz", 69 - "integrity": "sha512-6nVe9oV4Hdec6ctzMtW80TiDvNTd2oFPi3VsKqSDVaJSJbL+4b6seyJ7G/UEPI+si6JhHBSLV2/9lNXNGLjClA==", 70 - "cpu": [ 71 - "x64" 72 - ], 73 - "dev": true, 74 - "license": "Apache-2.0", 75 - "optional": true, 76 - "os": [ 77 - "darwin" 78 - ], 79 - "engines": { 80 - "node": ">=16" 81 - } 82 - }, 83 - "node_modules/@cloudflare/workerd-darwin-arm64": { 84 - "version": "1.20250428.0", 85 - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250428.0.tgz", 86 - "integrity": "sha512-/TB7bh7SIJ5f+6r4PHsAz7+9Qal/TK1cJuKFkUno1kqGlZbdrMwH0ATYwlWC/nBFeu2FB3NUolsTntEuy23hnQ==", 87 - "cpu": [ 88 - "arm64" 89 - ], 90 - "dev": true, 91 - "license": "Apache-2.0", 92 - "optional": true, 93 - "os": [ 94 - "darwin" 95 - ], 96 - "engines": { 97 - "node": ">=16" 98 - } 99 - }, 100 - "node_modules/@cloudflare/workerd-linux-64": { 101 - "version": "1.20250428.0", 102 - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250428.0.tgz", 103 - "integrity": "sha512-9eCbj+R3CKqpiXP6DfAA20DxKge+OTj7Hyw3ZewiEhWH9INIHiJwJQYybu4iq9kJEGjnGvxgguLFjSCWm26hgg==", 104 - "cpu": [ 105 - "x64" 106 - ], 107 - "dev": true, 108 - "license": "Apache-2.0", 109 - "optional": true, 110 - "os": [ 111 - "linux" 112 - ], 113 - "engines": { 114 - "node": ">=16" 115 - } 116 - }, 117 - "node_modules/@cloudflare/workerd-linux-arm64": { 118 - "version": "1.20250428.0", 119 - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250428.0.tgz", 120 - "integrity": "sha512-D9NRBnW46nl1EQsP13qfkYb5lbt4C6nxl38SBKY/NOcZAUoHzNB5K0GaK8LxvpkM7X/97ySojlMfR5jh5DNXYQ==", 121 - "cpu": [ 122 - "arm64" 123 - ], 124 - "dev": true, 125 - "license": "Apache-2.0", 126 - "optional": true, 127 - "os": [ 128 - "linux" 129 - ], 130 - "engines": { 131 - "node": ">=16" 132 - } 133 - }, 134 - "node_modules/@cloudflare/workerd-windows-64": { 135 - "version": "1.20250428.0", 136 - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250428.0.tgz", 137 - "integrity": "sha512-RQCRj28eitjKD0tmei6iFOuWqMuHMHdNGEigRmbkmuTlpbWHNAoHikgCzZQ/dkKDdatA76TmcpbyECNf31oaTA==", 138 - "cpu": [ 139 - "x64" 140 - ], 141 - "dev": true, 142 - "license": "Apache-2.0", 143 - "optional": true, 144 - "os": [ 145 - "win32" 146 - ], 147 - "engines": { 148 - "node": ">=16" 149 - } 150 - }, 151 - "node_modules/@cspotcode/source-map-support": { 152 - "version": "0.8.1", 153 - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", 154 - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", 155 - "dev": true, 156 - "license": "MIT", 157 - "dependencies": { 158 - "@jridgewell/trace-mapping": "0.3.9" 159 - }, 160 - "engines": { 161 - "node": ">=12" 162 - } 163 - }, 164 - "node_modules/@emnapi/runtime": { 165 - "version": "1.4.3", 166 - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", 167 - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", 168 - "dev": true, 169 - "license": "MIT", 170 - "optional": true, 171 - "dependencies": { 172 - "tslib": "^2.4.0" 173 - } 174 - }, 175 - "node_modules/@esbuild/aix-ppc64": { 176 - "version": "0.25.3", 177 - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", 178 - "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", 179 - "cpu": [ 180 - "ppc64" 181 - ], 182 - "dev": true, 183 - "license": "MIT", 184 - "optional": true, 185 - "os": [ 186 - "aix" 187 - ], 188 - "engines": { 189 - "node": ">=18" 190 - } 191 - }, 192 - "node_modules/@esbuild/android-arm": { 193 - "version": "0.25.3", 194 - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", 195 - "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", 196 - "cpu": [ 197 - "arm" 198 - ], 199 - "dev": true, 200 - "license": "MIT", 201 - "optional": true, 202 - "os": [ 203 - "android" 204 - ], 205 - "engines": { 206 - "node": ">=18" 207 - } 208 - }, 209 - "node_modules/@esbuild/android-arm64": { 210 - "version": "0.25.3", 211 - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", 212 - "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", 213 - "cpu": [ 214 - "arm64" 215 - ], 216 - "dev": true, 217 - "license": "MIT", 218 - "optional": true, 219 - "os": [ 220 - "android" 221 - ], 222 - "engines": { 223 - "node": ">=18" 224 - } 225 - }, 226 - "node_modules/@esbuild/android-x64": { 227 - "version": "0.25.3", 228 - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", 229 - "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", 230 - "cpu": [ 231 - "x64" 232 - ], 233 - "dev": true, 234 - "license": "MIT", 235 - "optional": true, 236 - "os": [ 237 - "android" 238 - ], 239 - "engines": { 240 - "node": ">=18" 241 - } 242 - }, 243 - "node_modules/@esbuild/darwin-arm64": { 244 - "version": "0.25.3", 245 - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", 246 - "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", 247 - "cpu": [ 248 - "arm64" 249 - ], 250 - "dev": true, 251 - "license": "MIT", 252 - "optional": true, 253 - "os": [ 254 - "darwin" 255 - ], 256 - "engines": { 257 - "node": ">=18" 258 - } 259 - }, 260 - "node_modules/@esbuild/darwin-x64": { 261 - "version": "0.25.3", 262 - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", 263 - "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", 264 - "cpu": [ 265 - "x64" 266 - ], 267 - "dev": true, 268 - "license": "MIT", 269 - "optional": true, 270 - "os": [ 271 - "darwin" 272 - ], 273 - "engines": { 274 - "node": ">=18" 275 - } 276 - }, 277 - "node_modules/@esbuild/freebsd-arm64": { 278 - "version": "0.25.3", 279 - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", 280 - "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", 281 - "cpu": [ 282 - "arm64" 283 - ], 284 - "dev": true, 285 - "license": "MIT", 286 - "optional": true, 287 - "os": [ 288 - "freebsd" 289 - ], 290 - "engines": { 291 - "node": ">=18" 292 - } 293 - }, 294 - "node_modules/@esbuild/freebsd-x64": { 295 - "version": "0.25.3", 296 - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", 297 - "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", 298 - "cpu": [ 299 - "x64" 300 - ], 301 - "dev": true, 302 - "license": "MIT", 303 - "optional": true, 304 - "os": [ 305 - "freebsd" 306 - ], 307 - "engines": { 308 - "node": ">=18" 309 - } 310 - }, 311 - "node_modules/@esbuild/linux-arm": { 312 - "version": "0.25.3", 313 - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", 314 - "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", 315 - "cpu": [ 316 - "arm" 317 - ], 318 - "dev": true, 319 - "license": "MIT", 320 - "optional": true, 321 - "os": [ 322 - "linux" 323 - ], 324 - "engines": { 325 - "node": ">=18" 326 - } 327 - }, 328 - "node_modules/@esbuild/linux-arm64": { 329 - "version": "0.25.3", 330 - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", 331 - "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", 332 - "cpu": [ 333 - "arm64" 334 - ], 335 - "dev": true, 336 - "license": "MIT", 337 - "optional": true, 338 - "os": [ 339 - "linux" 340 - ], 341 - "engines": { 342 - "node": ">=18" 343 - } 344 - }, 345 - "node_modules/@esbuild/linux-ia32": { 346 - "version": "0.25.3", 347 - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", 348 - "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", 349 - "cpu": [ 350 - "ia32" 351 - ], 352 - "dev": true, 353 - "license": "MIT", 354 - "optional": true, 355 - "os": [ 356 - "linux" 357 - ], 358 - "engines": { 359 - "node": ">=18" 360 - } 361 - }, 362 - "node_modules/@esbuild/linux-loong64": { 363 - "version": "0.25.3", 364 - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", 365 - "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", 366 - "cpu": [ 367 - "loong64" 368 - ], 369 - "dev": true, 370 - "license": "MIT", 371 - "optional": true, 372 - "os": [ 373 - "linux" 374 - ], 375 - "engines": { 376 - "node": ">=18" 377 - } 378 - }, 379 - "node_modules/@esbuild/linux-mips64el": { 380 - "version": "0.25.3", 381 - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", 382 - "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", 383 - "cpu": [ 384 - "mips64el" 385 - ], 386 - "dev": true, 387 - "license": "MIT", 388 - "optional": true, 389 - "os": [ 390 - "linux" 391 - ], 392 - "engines": { 393 - "node": ">=18" 394 - } 395 - }, 396 - "node_modules/@esbuild/linux-ppc64": { 397 - "version": "0.25.3", 398 - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", 399 - "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", 400 - "cpu": [ 401 - "ppc64" 402 - ], 403 - "dev": true, 404 - "license": "MIT", 405 - "optional": true, 406 - "os": [ 407 - "linux" 408 - ], 409 - "engines": { 410 - "node": ">=18" 411 - } 412 - }, 413 - "node_modules/@esbuild/linux-riscv64": { 414 - "version": "0.25.3", 415 - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", 416 - "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", 417 - "cpu": [ 418 - "riscv64" 419 - ], 420 - "dev": true, 421 - "license": "MIT", 422 - "optional": true, 423 - "os": [ 424 - "linux" 425 - ], 426 - "engines": { 427 - "node": ">=18" 428 - } 429 - }, 430 - "node_modules/@esbuild/linux-s390x": { 431 - "version": "0.25.3", 432 - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", 433 - "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", 434 - "cpu": [ 435 - "s390x" 436 - ], 437 - "dev": true, 438 - "license": "MIT", 439 - "optional": true, 440 - "os": [ 441 - "linux" 442 - ], 443 - "engines": { 444 - "node": ">=18" 445 - } 446 - }, 447 - "node_modules/@esbuild/linux-x64": { 448 - "version": "0.25.3", 449 - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", 450 - "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", 451 - "cpu": [ 452 - "x64" 453 - ], 454 - "dev": true, 455 - "license": "MIT", 456 - "optional": true, 457 - "os": [ 458 - "linux" 459 - ], 460 - "engines": { 461 - "node": ">=18" 462 - } 463 - }, 464 - "node_modules/@esbuild/netbsd-arm64": { 465 - "version": "0.25.3", 466 - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", 467 - "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", 468 - "cpu": [ 469 - "arm64" 470 - ], 471 - "dev": true, 472 - "license": "MIT", 473 - "optional": true, 474 - "os": [ 475 - "netbsd" 476 - ], 477 - "engines": { 478 - "node": ">=18" 479 - } 480 - }, 481 - "node_modules/@esbuild/netbsd-x64": { 482 - "version": "0.25.3", 483 - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", 484 - "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", 485 - "cpu": [ 486 - "x64" 487 - ], 488 - "dev": true, 489 - "license": "MIT", 490 - "optional": true, 491 - "os": [ 492 - "netbsd" 493 - ], 494 - "engines": { 495 - "node": ">=18" 496 - } 497 - }, 498 - "node_modules/@esbuild/openbsd-arm64": { 499 - "version": "0.25.3", 500 - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", 501 - "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", 502 - "cpu": [ 503 - "arm64" 504 - ], 505 - "dev": true, 506 - "license": "MIT", 507 - "optional": true, 508 - "os": [ 509 - "openbsd" 510 - ], 511 - "engines": { 512 - "node": ">=18" 513 - } 514 - }, 515 - "node_modules/@esbuild/openbsd-x64": { 516 - "version": "0.25.3", 517 - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", 518 - "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", 519 - "cpu": [ 520 - "x64" 521 - ], 522 - "dev": true, 523 - "license": "MIT", 524 - "optional": true, 525 - "os": [ 526 - "openbsd" 527 - ], 528 - "engines": { 529 - "node": ">=18" 530 - } 531 - }, 532 - "node_modules/@esbuild/sunos-x64": { 533 - "version": "0.25.3", 534 - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", 535 - "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", 536 - "cpu": [ 537 - "x64" 538 - ], 539 - "dev": true, 540 - "license": "MIT", 541 - "optional": true, 542 - "os": [ 543 - "sunos" 544 - ], 545 - "engines": { 546 - "node": ">=18" 547 - } 548 - }, 549 - "node_modules/@esbuild/win32-arm64": { 550 - "version": "0.25.3", 551 - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", 552 - "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", 553 - "cpu": [ 554 - "arm64" 555 - ], 556 - "dev": true, 557 - "license": "MIT", 558 - "optional": true, 559 - "os": [ 560 - "win32" 561 - ], 562 - "engines": { 563 - "node": ">=18" 564 - } 565 - }, 566 - "node_modules/@esbuild/win32-ia32": { 567 - "version": "0.25.3", 568 - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", 569 - "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", 570 - "cpu": [ 571 - "ia32" 572 - ], 573 - "dev": true, 574 - "license": "MIT", 575 - "optional": true, 576 - "os": [ 577 - "win32" 578 - ], 579 - "engines": { 580 - "node": ">=18" 581 - } 582 - }, 583 - "node_modules/@esbuild/win32-x64": { 584 - "version": "0.25.3", 585 - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", 586 - "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", 587 - "cpu": [ 588 - "x64" 589 - ], 590 - "dev": true, 591 - "license": "MIT", 592 - "optional": true, 593 - "os": [ 594 - "win32" 595 - ], 596 - "engines": { 597 - "node": ">=18" 598 - } 599 - }, 600 - "node_modules/@fastify/busboy": { 601 - "version": "2.1.1", 602 - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", 603 - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", 604 - "dev": true, 605 - "license": "MIT", 606 - "engines": { 607 - "node": ">=14" 608 - } 609 - }, 610 - "node_modules/@img/sharp-darwin-arm64": { 611 - "version": "0.33.5", 612 - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", 613 - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", 614 - "cpu": [ 615 - "arm64" 616 - ], 617 - "dev": true, 618 - "license": "Apache-2.0", 619 - "optional": true, 620 - "os": [ 621 - "darwin" 622 - ], 623 - "engines": { 624 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 625 - }, 626 - "funding": { 627 - "url": "https://opencollective.com/libvips" 628 - }, 629 - "optionalDependencies": { 630 - "@img/sharp-libvips-darwin-arm64": "1.0.4" 631 - } 632 - }, 633 - "node_modules/@img/sharp-darwin-x64": { 634 - "version": "0.33.5", 635 - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", 636 - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", 637 - "cpu": [ 638 - "x64" 639 - ], 640 - "dev": true, 641 - "license": "Apache-2.0", 642 - "optional": true, 643 - "os": [ 644 - "darwin" 645 - ], 646 - "engines": { 647 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 648 - }, 649 - "funding": { 650 - "url": "https://opencollective.com/libvips" 651 - }, 652 - "optionalDependencies": { 653 - "@img/sharp-libvips-darwin-x64": "1.0.4" 654 - } 655 - }, 656 - "node_modules/@img/sharp-libvips-darwin-arm64": { 657 - "version": "1.0.4", 658 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", 659 - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", 660 - "cpu": [ 661 - "arm64" 662 - ], 663 - "dev": true, 664 - "license": "LGPL-3.0-or-later", 665 - "optional": true, 666 - "os": [ 667 - "darwin" 668 - ], 669 - "funding": { 670 - "url": "https://opencollective.com/libvips" 671 - } 672 - }, 673 - "node_modules/@img/sharp-libvips-darwin-x64": { 674 - "version": "1.0.4", 675 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", 676 - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", 677 - "cpu": [ 678 - "x64" 679 - ], 680 - "dev": true, 681 - "license": "LGPL-3.0-or-later", 682 - "optional": true, 683 - "os": [ 684 - "darwin" 685 - ], 686 - "funding": { 687 - "url": "https://opencollective.com/libvips" 688 - } 689 - }, 690 - "node_modules/@img/sharp-libvips-linux-arm": { 691 - "version": "1.0.5", 692 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", 693 - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", 694 - "cpu": [ 695 - "arm" 696 - ], 697 - "dev": true, 698 - "license": "LGPL-3.0-or-later", 699 - "optional": true, 700 - "os": [ 701 - "linux" 702 - ], 703 - "funding": { 704 - "url": "https://opencollective.com/libvips" 705 - } 706 - }, 707 - "node_modules/@img/sharp-libvips-linux-arm64": { 708 - "version": "1.0.4", 709 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", 710 - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", 711 - "cpu": [ 712 - "arm64" 713 - ], 714 - "dev": true, 715 - "license": "LGPL-3.0-or-later", 716 - "optional": true, 717 - "os": [ 718 - "linux" 719 - ], 720 - "funding": { 721 - "url": "https://opencollective.com/libvips" 722 - } 723 - }, 724 - "node_modules/@img/sharp-libvips-linux-s390x": { 725 - "version": "1.0.4", 726 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", 727 - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", 728 - "cpu": [ 729 - "s390x" 730 - ], 731 - "dev": true, 732 - "license": "LGPL-3.0-or-later", 733 - "optional": true, 734 - "os": [ 735 - "linux" 736 - ], 737 - "funding": { 738 - "url": "https://opencollective.com/libvips" 739 - } 740 - }, 741 - "node_modules/@img/sharp-libvips-linux-x64": { 742 - "version": "1.0.4", 743 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", 744 - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", 745 - "cpu": [ 746 - "x64" 747 - ], 748 - "dev": true, 749 - "license": "LGPL-3.0-or-later", 750 - "optional": true, 751 - "os": [ 752 - "linux" 753 - ], 754 - "funding": { 755 - "url": "https://opencollective.com/libvips" 756 - } 757 - }, 758 - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { 759 - "version": "1.0.4", 760 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", 761 - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", 762 - "cpu": [ 763 - "arm64" 764 - ], 765 - "dev": true, 766 - "license": "LGPL-3.0-or-later", 767 - "optional": true, 768 - "os": [ 769 - "linux" 770 - ], 771 - "funding": { 772 - "url": "https://opencollective.com/libvips" 773 - } 774 - }, 775 - "node_modules/@img/sharp-libvips-linuxmusl-x64": { 776 - "version": "1.0.4", 777 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", 778 - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", 779 - "cpu": [ 780 - "x64" 781 - ], 782 - "dev": true, 783 - "license": "LGPL-3.0-or-later", 784 - "optional": true, 785 - "os": [ 786 - "linux" 787 - ], 788 - "funding": { 789 - "url": "https://opencollective.com/libvips" 790 - } 791 - }, 792 - "node_modules/@img/sharp-linux-arm": { 793 - "version": "0.33.5", 794 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", 795 - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", 796 - "cpu": [ 797 - "arm" 798 - ], 799 - "dev": true, 800 - "license": "Apache-2.0", 801 - "optional": true, 802 - "os": [ 803 - "linux" 804 - ], 805 - "engines": { 806 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 807 - }, 808 - "funding": { 809 - "url": "https://opencollective.com/libvips" 810 - }, 811 - "optionalDependencies": { 812 - "@img/sharp-libvips-linux-arm": "1.0.5" 813 - } 814 - }, 815 - "node_modules/@img/sharp-linux-arm64": { 816 - "version": "0.33.5", 817 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", 818 - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", 819 - "cpu": [ 820 - "arm64" 821 - ], 822 - "dev": true, 823 - "license": "Apache-2.0", 824 - "optional": true, 825 - "os": [ 826 - "linux" 827 - ], 828 - "engines": { 829 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 830 - }, 831 - "funding": { 832 - "url": "https://opencollective.com/libvips" 833 - }, 834 - "optionalDependencies": { 835 - "@img/sharp-libvips-linux-arm64": "1.0.4" 836 - } 837 - }, 838 - "node_modules/@img/sharp-linux-s390x": { 839 - "version": "0.33.5", 840 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", 841 - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", 842 - "cpu": [ 843 - "s390x" 844 - ], 845 - "dev": true, 846 - "license": "Apache-2.0", 847 - "optional": true, 848 - "os": [ 849 - "linux" 850 - ], 851 - "engines": { 852 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 853 - }, 854 - "funding": { 855 - "url": "https://opencollective.com/libvips" 856 - }, 857 - "optionalDependencies": { 858 - "@img/sharp-libvips-linux-s390x": "1.0.4" 859 - } 860 - }, 861 - "node_modules/@img/sharp-linux-x64": { 862 - "version": "0.33.5", 863 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", 864 - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", 865 - "cpu": [ 866 - "x64" 867 - ], 868 - "dev": true, 869 - "license": "Apache-2.0", 870 - "optional": true, 871 - "os": [ 872 - "linux" 873 - ], 874 - "engines": { 875 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 876 - }, 877 - "funding": { 878 - "url": "https://opencollective.com/libvips" 879 - }, 880 - "optionalDependencies": { 881 - "@img/sharp-libvips-linux-x64": "1.0.4" 882 - } 883 - }, 884 - "node_modules/@img/sharp-linuxmusl-arm64": { 885 - "version": "0.33.5", 886 - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", 887 - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", 888 - "cpu": [ 889 - "arm64" 890 - ], 891 - "dev": true, 892 - "license": "Apache-2.0", 893 - "optional": true, 894 - "os": [ 895 - "linux" 896 - ], 897 - "engines": { 898 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 899 - }, 900 - "funding": { 901 - "url": "https://opencollective.com/libvips" 902 - }, 903 - "optionalDependencies": { 904 - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" 905 - } 906 - }, 907 - "node_modules/@img/sharp-linuxmusl-x64": { 908 - "version": "0.33.5", 909 - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", 910 - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", 911 - "cpu": [ 912 - "x64" 913 - ], 914 - "dev": true, 915 - "license": "Apache-2.0", 916 - "optional": true, 917 - "os": [ 918 - "linux" 919 - ], 920 - "engines": { 921 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 922 - }, 923 - "funding": { 924 - "url": "https://opencollective.com/libvips" 925 - }, 926 - "optionalDependencies": { 927 - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" 928 - } 929 - }, 930 - "node_modules/@img/sharp-wasm32": { 931 - "version": "0.33.5", 932 - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", 933 - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", 934 - "cpu": [ 935 - "wasm32" 936 - ], 937 - "dev": true, 938 - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", 939 - "optional": true, 940 - "dependencies": { 941 - "@emnapi/runtime": "^1.2.0" 942 - }, 943 - "engines": { 944 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 945 - }, 946 - "funding": { 947 - "url": "https://opencollective.com/libvips" 948 - } 949 - }, 950 - "node_modules/@img/sharp-win32-ia32": { 951 - "version": "0.33.5", 952 - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", 953 - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", 954 - "cpu": [ 955 - "ia32" 956 - ], 957 - "dev": true, 958 - "license": "Apache-2.0 AND LGPL-3.0-or-later", 959 - "optional": true, 960 - "os": [ 961 - "win32" 962 - ], 963 - "engines": { 964 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 965 - }, 966 - "funding": { 967 - "url": "https://opencollective.com/libvips" 968 - } 969 - }, 970 - "node_modules/@img/sharp-win32-x64": { 971 - "version": "0.33.5", 972 - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", 973 - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", 974 - "cpu": [ 975 - "x64" 976 - ], 977 - "dev": true, 978 - "license": "Apache-2.0 AND LGPL-3.0-or-later", 979 - "optional": true, 980 - "os": [ 981 - "win32" 982 - ], 983 - "engines": { 984 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 985 - }, 986 - "funding": { 987 - "url": "https://opencollective.com/libvips" 988 - } 989 - }, 990 - "node_modules/@jridgewell/resolve-uri": { 991 - "version": "3.1.2", 992 - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 993 - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 994 - "dev": true, 995 - "license": "MIT", 996 - "engines": { 997 - "node": ">=6.0.0" 998 - } 999 - }, 1000 - "node_modules/@jridgewell/sourcemap-codec": { 1001 - "version": "1.5.0", 1002 - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 1003 - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 1004 - "dev": true, 1005 - "license": "MIT" 1006 - }, 1007 - "node_modules/@jridgewell/trace-mapping": { 1008 - "version": "0.3.9", 1009 - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", 1010 - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", 1011 - "dev": true, 1012 - "license": "MIT", 1013 - "dependencies": { 1014 - "@jridgewell/resolve-uri": "^3.0.3", 1015 - "@jridgewell/sourcemap-codec": "^1.4.10" 1016 - } 1017 - }, 1018 - "node_modules/@rollup/rollup-android-arm-eabi": { 1019 - "version": "4.40.1", 1020 - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.1.tgz", 1021 - "integrity": "sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==", 1022 - "cpu": [ 1023 - "arm" 1024 - ], 1025 - "dev": true, 1026 - "license": "MIT", 1027 - "optional": true, 1028 - "os": [ 1029 - "android" 1030 - ] 1031 - }, 1032 - "node_modules/@rollup/rollup-android-arm64": { 1033 - "version": "4.40.1", 1034 - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.1.tgz", 1035 - "integrity": "sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==", 1036 - "cpu": [ 1037 - "arm64" 1038 - ], 1039 - "dev": true, 1040 - "license": "MIT", 1041 - "optional": true, 1042 - "os": [ 1043 - "android" 1044 - ] 1045 - }, 1046 - "node_modules/@rollup/rollup-darwin-arm64": { 1047 - "version": "4.40.1", 1048 - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.1.tgz", 1049 - "integrity": "sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==", 1050 - "cpu": [ 1051 - "arm64" 1052 - ], 1053 - "dev": true, 1054 - "license": "MIT", 1055 - "optional": true, 1056 - "os": [ 1057 - "darwin" 1058 - ] 1059 - }, 1060 - "node_modules/@rollup/rollup-darwin-x64": { 1061 - "version": "4.40.1", 1062 - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.1.tgz", 1063 - "integrity": "sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==", 1064 - "cpu": [ 1065 - "x64" 1066 - ], 1067 - "dev": true, 1068 - "license": "MIT", 1069 - "optional": true, 1070 - "os": [ 1071 - "darwin" 1072 - ] 1073 - }, 1074 - "node_modules/@rollup/rollup-freebsd-arm64": { 1075 - "version": "4.40.1", 1076 - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.1.tgz", 1077 - "integrity": "sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==", 1078 - "cpu": [ 1079 - "arm64" 1080 - ], 1081 - "dev": true, 1082 - "license": "MIT", 1083 - "optional": true, 1084 - "os": [ 1085 - "freebsd" 1086 - ] 1087 - }, 1088 - "node_modules/@rollup/rollup-freebsd-x64": { 1089 - "version": "4.40.1", 1090 - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.1.tgz", 1091 - "integrity": "sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==", 1092 - "cpu": [ 1093 - "x64" 1094 - ], 1095 - "dev": true, 1096 - "license": "MIT", 1097 - "optional": true, 1098 - "os": [ 1099 - "freebsd" 1100 - ] 1101 - }, 1102 - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 1103 - "version": "4.40.1", 1104 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.1.tgz", 1105 - "integrity": "sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==", 1106 - "cpu": [ 1107 - "arm" 1108 - ], 1109 - "dev": true, 1110 - "license": "MIT", 1111 - "optional": true, 1112 - "os": [ 1113 - "linux" 1114 - ] 1115 - }, 1116 - "node_modules/@rollup/rollup-linux-arm-musleabihf": { 1117 - "version": "4.40.1", 1118 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.1.tgz", 1119 - "integrity": "sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==", 1120 - "cpu": [ 1121 - "arm" 1122 - ], 1123 - "dev": true, 1124 - "license": "MIT", 1125 - "optional": true, 1126 - "os": [ 1127 - "linux" 1128 - ] 1129 - }, 1130 - "node_modules/@rollup/rollup-linux-arm64-gnu": { 1131 - "version": "4.40.1", 1132 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.1.tgz", 1133 - "integrity": "sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==", 1134 - "cpu": [ 1135 - "arm64" 1136 - ], 1137 - "dev": true, 1138 - "license": "MIT", 1139 - "optional": true, 1140 - "os": [ 1141 - "linux" 1142 - ] 1143 - }, 1144 - "node_modules/@rollup/rollup-linux-arm64-musl": { 1145 - "version": "4.40.1", 1146 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.1.tgz", 1147 - "integrity": "sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==", 1148 - "cpu": [ 1149 - "arm64" 1150 - ], 1151 - "dev": true, 1152 - "license": "MIT", 1153 - "optional": true, 1154 - "os": [ 1155 - "linux" 1156 - ] 1157 - }, 1158 - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 1159 - "version": "4.40.1", 1160 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.1.tgz", 1161 - "integrity": "sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==", 1162 - "cpu": [ 1163 - "loong64" 1164 - ], 1165 - "dev": true, 1166 - "license": "MIT", 1167 - "optional": true, 1168 - "os": [ 1169 - "linux" 1170 - ] 1171 - }, 1172 - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 1173 - "version": "4.40.1", 1174 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.1.tgz", 1175 - "integrity": "sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==", 1176 - "cpu": [ 1177 - "ppc64" 1178 - ], 1179 - "dev": true, 1180 - "license": "MIT", 1181 - "optional": true, 1182 - "os": [ 1183 - "linux" 1184 - ] 1185 - }, 1186 - "node_modules/@rollup/rollup-linux-riscv64-gnu": { 1187 - "version": "4.40.1", 1188 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.1.tgz", 1189 - "integrity": "sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==", 1190 - "cpu": [ 1191 - "riscv64" 1192 - ], 1193 - "dev": true, 1194 - "license": "MIT", 1195 - "optional": true, 1196 - "os": [ 1197 - "linux" 1198 - ] 1199 - }, 1200 - "node_modules/@rollup/rollup-linux-riscv64-musl": { 1201 - "version": "4.40.1", 1202 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.1.tgz", 1203 - "integrity": "sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==", 1204 - "cpu": [ 1205 - "riscv64" 1206 - ], 1207 - "dev": true, 1208 - "license": "MIT", 1209 - "optional": true, 1210 - "os": [ 1211 - "linux" 1212 - ] 1213 - }, 1214 - "node_modules/@rollup/rollup-linux-s390x-gnu": { 1215 - "version": "4.40.1", 1216 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.1.tgz", 1217 - "integrity": "sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==", 1218 - "cpu": [ 1219 - "s390x" 1220 - ], 1221 - "dev": true, 1222 - "license": "MIT", 1223 - "optional": true, 1224 - "os": [ 1225 - "linux" 1226 - ] 1227 - }, 1228 - "node_modules/@rollup/rollup-linux-x64-gnu": { 1229 - "version": "4.40.1", 1230 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.1.tgz", 1231 - "integrity": "sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==", 1232 - "cpu": [ 1233 - "x64" 1234 - ], 1235 - "dev": true, 1236 - "license": "MIT", 1237 - "optional": true, 1238 - "os": [ 1239 - "linux" 1240 - ] 1241 - }, 1242 - "node_modules/@rollup/rollup-linux-x64-musl": { 1243 - "version": "4.40.1", 1244 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.1.tgz", 1245 - "integrity": "sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==", 1246 - "cpu": [ 1247 - "x64" 1248 - ], 1249 - "dev": true, 1250 - "license": "MIT", 1251 - "optional": true, 1252 - "os": [ 1253 - "linux" 1254 - ] 1255 - }, 1256 - "node_modules/@rollup/rollup-win32-arm64-msvc": { 1257 - "version": "4.40.1", 1258 - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.1.tgz", 1259 - "integrity": "sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==", 1260 - "cpu": [ 1261 - "arm64" 1262 - ], 1263 - "dev": true, 1264 - "license": "MIT", 1265 - "optional": true, 1266 - "os": [ 1267 - "win32" 1268 - ] 1269 - }, 1270 - "node_modules/@rollup/rollup-win32-ia32-msvc": { 1271 - "version": "4.40.1", 1272 - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.1.tgz", 1273 - "integrity": "sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==", 1274 - "cpu": [ 1275 - "ia32" 1276 - ], 1277 - "dev": true, 1278 - "license": "MIT", 1279 - "optional": true, 1280 - "os": [ 1281 - "win32" 1282 - ] 1283 - }, 1284 - "node_modules/@rollup/rollup-win32-x64-msvc": { 1285 - "version": "4.40.1", 1286 - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.1.tgz", 1287 - "integrity": "sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==", 1288 - "cpu": [ 1289 - "x64" 1290 - ], 1291 - "dev": true, 1292 - "license": "MIT", 1293 - "optional": true, 1294 - "os": [ 1295 - "win32" 1296 - ] 1297 - }, 1298 - "node_modules/@types/estree": { 1299 - "version": "1.0.7", 1300 - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", 1301 - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", 1302 - "dev": true, 1303 - "license": "MIT" 1304 - }, 1305 - "node_modules/@vitest/expect": { 1306 - "version": "3.0.9", 1307 - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", 1308 - "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", 1309 - "dev": true, 1310 - "license": "MIT", 1311 - "dependencies": { 1312 - "@vitest/spy": "3.0.9", 1313 - "@vitest/utils": "3.0.9", 1314 - "chai": "^5.2.0", 1315 - "tinyrainbow": "^2.0.0" 1316 - }, 1317 - "funding": { 1318 - "url": "https://opencollective.com/vitest" 1319 - } 1320 - }, 1321 - "node_modules/@vitest/mocker": { 1322 - "version": "3.0.9", 1323 - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", 1324 - "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", 1325 - "dev": true, 1326 - "license": "MIT", 1327 - "dependencies": { 1328 - "@vitest/spy": "3.0.9", 1329 - "estree-walker": "^3.0.3", 1330 - "magic-string": "^0.30.17" 1331 - }, 1332 - "funding": { 1333 - "url": "https://opencollective.com/vitest" 1334 - }, 1335 - "peerDependencies": { 1336 - "msw": "^2.4.9", 1337 - "vite": "^5.0.0 || ^6.0.0" 1338 - }, 1339 - "peerDependenciesMeta": { 1340 - "msw": { 1341 - "optional": true 1342 - }, 1343 - "vite": { 1344 - "optional": true 1345 - } 1346 - } 1347 - }, 1348 - "node_modules/@vitest/pretty-format": { 1349 - "version": "3.1.2", 1350 - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", 1351 - "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", 1352 - "dev": true, 1353 - "license": "MIT", 1354 - "dependencies": { 1355 - "tinyrainbow": "^2.0.0" 1356 - }, 1357 - "funding": { 1358 - "url": "https://opencollective.com/vitest" 1359 - } 1360 - }, 1361 - "node_modules/@vitest/runner": { 1362 - "version": "3.0.9", 1363 - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", 1364 - "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", 1365 - "dev": true, 1366 - "license": "MIT", 1367 - "dependencies": { 1368 - "@vitest/utils": "3.0.9", 1369 - "pathe": "^2.0.3" 1370 - }, 1371 - "funding": { 1372 - "url": "https://opencollective.com/vitest" 1373 - } 1374 - }, 1375 - "node_modules/@vitest/snapshot": { 1376 - "version": "3.0.9", 1377 - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", 1378 - "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", 1379 - "dev": true, 1380 - "license": "MIT", 1381 - "dependencies": { 1382 - "@vitest/pretty-format": "3.0.9", 1383 - "magic-string": "^0.30.17", 1384 - "pathe": "^2.0.3" 1385 - }, 1386 - "funding": { 1387 - "url": "https://opencollective.com/vitest" 1388 - } 1389 - }, 1390 - "node_modules/@vitest/snapshot/node_modules/@vitest/pretty-format": { 1391 - "version": "3.0.9", 1392 - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", 1393 - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", 1394 - "dev": true, 1395 - "license": "MIT", 1396 - "dependencies": { 1397 - "tinyrainbow": "^2.0.0" 1398 - }, 1399 - "funding": { 1400 - "url": "https://opencollective.com/vitest" 1401 - } 1402 - }, 1403 - "node_modules/@vitest/spy": { 1404 - "version": "3.0.9", 1405 - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", 1406 - "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", 1407 - "dev": true, 1408 - "license": "MIT", 1409 - "dependencies": { 1410 - "tinyspy": "^3.0.2" 1411 - }, 1412 - "funding": { 1413 - "url": "https://opencollective.com/vitest" 1414 - } 1415 - }, 1416 - "node_modules/@vitest/utils": { 1417 - "version": "3.0.9", 1418 - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", 1419 - "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", 1420 - "dev": true, 1421 - "license": "MIT", 1422 - "dependencies": { 1423 - "@vitest/pretty-format": "3.0.9", 1424 - "loupe": "^3.1.3", 1425 - "tinyrainbow": "^2.0.0" 1426 - }, 1427 - "funding": { 1428 - "url": "https://opencollective.com/vitest" 1429 - } 1430 - }, 1431 - "node_modules/@vitest/utils/node_modules/@vitest/pretty-format": { 1432 - "version": "3.0.9", 1433 - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", 1434 - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", 1435 - "dev": true, 1436 - "license": "MIT", 1437 - "dependencies": { 1438 - "tinyrainbow": "^2.0.0" 1439 - }, 1440 - "funding": { 1441 - "url": "https://opencollective.com/vitest" 1442 - } 1443 - }, 1444 - "node_modules/acorn": { 1445 - "version": "8.14.0", 1446 - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", 1447 - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", 1448 - "dev": true, 1449 - "license": "MIT", 1450 - "bin": { 1451 - "acorn": "bin/acorn" 1452 - }, 1453 - "engines": { 1454 - "node": ">=0.4.0" 1455 - } 1456 - }, 1457 - "node_modules/acorn-walk": { 1458 - "version": "8.3.2", 1459 - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", 1460 - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", 1461 - "dev": true, 1462 - "license": "MIT", 1463 - "engines": { 1464 - "node": ">=0.4.0" 1465 - } 1466 - }, 1467 - "node_modules/as-table": { 1468 - "version": "1.0.55", 1469 - "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", 1470 - "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", 1471 - "dev": true, 1472 - "license": "MIT", 1473 - "dependencies": { 1474 - "printable-characters": "^1.0.42" 1475 - } 1476 - }, 1477 - "node_modules/assertion-error": { 1478 - "version": "2.0.1", 1479 - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", 1480 - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", 1481 - "dev": true, 1482 - "license": "MIT", 1483 - "engines": { 1484 - "node": ">=12" 1485 - } 1486 - }, 1487 - "node_modules/birpc": { 1488 - "version": "0.2.14", 1489 - "resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.14.tgz", 1490 - "integrity": "sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA==", 1491 - "dev": true, 1492 - "license": "MIT", 1493 - "funding": { 1494 - "url": "https://github.com/sponsors/antfu" 1495 - } 1496 - }, 1497 - "node_modules/blake3-wasm": { 1498 - "version": "2.1.5", 1499 - "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", 1500 - "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", 1501 - "dev": true, 1502 - "license": "MIT" 1503 - }, 1504 - "node_modules/cac": { 1505 - "version": "6.7.14", 1506 - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 1507 - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 1508 - "dev": true, 1509 - "license": "MIT", 1510 - "engines": { 1511 - "node": ">=8" 1512 - } 1513 - }, 1514 - "node_modules/chai": { 1515 - "version": "5.2.0", 1516 - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", 1517 - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", 1518 - "dev": true, 1519 - "license": "MIT", 1520 - "dependencies": { 1521 - "assertion-error": "^2.0.1", 1522 - "check-error": "^2.1.1", 1523 - "deep-eql": "^5.0.1", 1524 - "loupe": "^3.1.0", 1525 - "pathval": "^2.0.0" 1526 - }, 1527 - "engines": { 1528 - "node": ">=12" 1529 - } 1530 - }, 1531 - "node_modules/check-error": { 1532 - "version": "2.1.1", 1533 - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", 1534 - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", 1535 - "dev": true, 1536 - "license": "MIT", 1537 - "engines": { 1538 - "node": ">= 16" 1539 - } 1540 - }, 1541 - "node_modules/cjs-module-lexer": { 1542 - "version": "1.4.3", 1543 - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", 1544 - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", 1545 - "dev": true, 1546 - "license": "MIT" 1547 - }, 1548 - "node_modules/color": { 1549 - "version": "4.2.3", 1550 - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", 1551 - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", 1552 - "dev": true, 1553 - "license": "MIT", 1554 - "optional": true, 1555 - "dependencies": { 1556 - "color-convert": "^2.0.1", 1557 - "color-string": "^1.9.0" 1558 - }, 1559 - "engines": { 1560 - "node": ">=12.5.0" 1561 - } 1562 - }, 1563 - "node_modules/color-convert": { 1564 - "version": "2.0.1", 1565 - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1566 - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1567 - "dev": true, 1568 - "license": "MIT", 1569 - "optional": true, 1570 - "dependencies": { 1571 - "color-name": "~1.1.4" 1572 - }, 1573 - "engines": { 1574 - "node": ">=7.0.0" 1575 - } 1576 - }, 1577 - "node_modules/color-name": { 1578 - "version": "1.1.4", 1579 - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1580 - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1581 - "dev": true, 1582 - "license": "MIT", 1583 - "optional": true 1584 - }, 1585 - "node_modules/color-string": { 1586 - "version": "1.9.1", 1587 - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", 1588 - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", 1589 - "dev": true, 1590 - "license": "MIT", 1591 - "optional": true, 1592 - "dependencies": { 1593 - "color-name": "^1.0.0", 1594 - "simple-swizzle": "^0.2.2" 1595 - } 1596 - }, 1597 - "node_modules/cookie": { 1598 - "version": "0.7.2", 1599 - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 1600 - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 1601 - "dev": true, 1602 - "license": "MIT", 1603 - "engines": { 1604 - "node": ">= 0.6" 1605 - } 1606 - }, 1607 - "node_modules/data-uri-to-buffer": { 1608 - "version": "2.0.2", 1609 - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", 1610 - "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", 1611 - "dev": true, 1612 - "license": "MIT" 1613 - }, 1614 - "node_modules/debug": { 1615 - "version": "4.4.0", 1616 - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 1617 - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 1618 - "dev": true, 1619 - "license": "MIT", 1620 - "dependencies": { 1621 - "ms": "^2.1.3" 1622 - }, 1623 - "engines": { 1624 - "node": ">=6.0" 1625 - }, 1626 - "peerDependenciesMeta": { 1627 - "supports-color": { 1628 - "optional": true 1629 - } 1630 - } 1631 - }, 1632 - "node_modules/deep-eql": { 1633 - "version": "5.0.2", 1634 - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", 1635 - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", 1636 - "dev": true, 1637 - "license": "MIT", 1638 - "engines": { 1639 - "node": ">=6" 1640 - } 1641 - }, 1642 - "node_modules/defu": { 1643 - "version": "6.1.4", 1644 - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", 1645 - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", 1646 - "dev": true, 1647 - "license": "MIT" 1648 - }, 1649 - "node_modules/detect-libc": { 1650 - "version": "2.0.4", 1651 - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", 1652 - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", 1653 - "dev": true, 1654 - "license": "Apache-2.0", 1655 - "optional": true, 1656 - "engines": { 1657 - "node": ">=8" 1658 - } 1659 - }, 1660 - "node_modules/devalue": { 1661 - "version": "4.3.3", 1662 - "resolved": "https://registry.npmjs.org/devalue/-/devalue-4.3.3.tgz", 1663 - "integrity": "sha512-UH8EL6H2ifcY8TbD2QsxwCC/pr5xSwPvv85LrLXVihmHVC3T3YqTCIwnR5ak0yO1KYqlxrPVOA/JVZJYPy2ATg==", 1664 - "dev": true, 1665 - "license": "MIT" 1666 - }, 1667 - "node_modules/es-module-lexer": { 1668 - "version": "1.7.0", 1669 - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", 1670 - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", 1671 - "dev": true, 1672 - "license": "MIT" 1673 - }, 1674 - "node_modules/esbuild": { 1675 - "version": "0.25.3", 1676 - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", 1677 - "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", 1678 - "dev": true, 1679 - "hasInstallScript": true, 1680 - "license": "MIT", 1681 - "bin": { 1682 - "esbuild": "bin/esbuild" 1683 - }, 1684 - "engines": { 1685 - "node": ">=18" 1686 - }, 1687 - "optionalDependencies": { 1688 - "@esbuild/aix-ppc64": "0.25.3", 1689 - "@esbuild/android-arm": "0.25.3", 1690 - "@esbuild/android-arm64": "0.25.3", 1691 - "@esbuild/android-x64": "0.25.3", 1692 - "@esbuild/darwin-arm64": "0.25.3", 1693 - "@esbuild/darwin-x64": "0.25.3", 1694 - "@esbuild/freebsd-arm64": "0.25.3", 1695 - "@esbuild/freebsd-x64": "0.25.3", 1696 - "@esbuild/linux-arm": "0.25.3", 1697 - "@esbuild/linux-arm64": "0.25.3", 1698 - "@esbuild/linux-ia32": "0.25.3", 1699 - "@esbuild/linux-loong64": "0.25.3", 1700 - "@esbuild/linux-mips64el": "0.25.3", 1701 - "@esbuild/linux-ppc64": "0.25.3", 1702 - "@esbuild/linux-riscv64": "0.25.3", 1703 - "@esbuild/linux-s390x": "0.25.3", 1704 - "@esbuild/linux-x64": "0.25.3", 1705 - "@esbuild/netbsd-arm64": "0.25.3", 1706 - "@esbuild/netbsd-x64": "0.25.3", 1707 - "@esbuild/openbsd-arm64": "0.25.3", 1708 - "@esbuild/openbsd-x64": "0.25.3", 1709 - "@esbuild/sunos-x64": "0.25.3", 1710 - "@esbuild/win32-arm64": "0.25.3", 1711 - "@esbuild/win32-ia32": "0.25.3", 1712 - "@esbuild/win32-x64": "0.25.3" 1713 - } 1714 - }, 1715 - "node_modules/estree-walker": { 1716 - "version": "3.0.3", 1717 - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", 1718 - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", 1719 - "dev": true, 1720 - "license": "MIT", 1721 - "dependencies": { 1722 - "@types/estree": "^1.0.0" 1723 - } 1724 - }, 1725 - "node_modules/exit-hook": { 1726 - "version": "2.2.1", 1727 - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", 1728 - "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", 1729 - "dev": true, 1730 - "license": "MIT", 1731 - "engines": { 1732 - "node": ">=6" 1733 - }, 1734 - "funding": { 1735 - "url": "https://github.com/sponsors/sindresorhus" 1736 - } 1737 - }, 1738 - "node_modules/expect-type": { 1739 - "version": "1.2.1", 1740 - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", 1741 - "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", 1742 - "dev": true, 1743 - "license": "Apache-2.0", 1744 - "engines": { 1745 - "node": ">=12.0.0" 1746 - } 1747 - }, 1748 - "node_modules/exsolve": { 1749 - "version": "1.0.5", 1750 - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", 1751 - "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", 1752 - "dev": true, 1753 - "license": "MIT" 1754 - }, 1755 - "node_modules/fdir": { 1756 - "version": "6.4.4", 1757 - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", 1758 - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", 1759 - "dev": true, 1760 - "license": "MIT", 1761 - "peerDependencies": { 1762 - "picomatch": "^3 || ^4" 1763 - }, 1764 - "peerDependenciesMeta": { 1765 - "picomatch": { 1766 - "optional": true 1767 - } 1768 - } 1769 - }, 1770 - "node_modules/fsevents": { 1771 - "version": "2.3.3", 1772 - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1773 - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1774 - "dev": true, 1775 - "hasInstallScript": true, 1776 - "license": "MIT", 1777 - "optional": true, 1778 - "os": [ 1779 - "darwin" 1780 - ], 1781 - "engines": { 1782 - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1783 - } 1784 - }, 1785 - "node_modules/get-source": { 1786 - "version": "2.0.12", 1787 - "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", 1788 - "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", 1789 - "dev": true, 1790 - "license": "Unlicense", 1791 - "dependencies": { 1792 - "data-uri-to-buffer": "^2.0.0", 1793 - "source-map": "^0.6.1" 1794 - } 1795 - }, 1796 - "node_modules/glob-to-regexp": { 1797 - "version": "0.4.1", 1798 - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", 1799 - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", 1800 - "dev": true, 1801 - "license": "BSD-2-Clause" 1802 - }, 1803 - "node_modules/is-arrayish": { 1804 - "version": "0.3.2", 1805 - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", 1806 - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", 1807 - "dev": true, 1808 - "license": "MIT", 1809 - "optional": true 1810 - }, 1811 - "node_modules/loupe": { 1812 - "version": "3.1.3", 1813 - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", 1814 - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", 1815 - "dev": true, 1816 - "license": "MIT" 1817 - }, 1818 - "node_modules/magic-string": { 1819 - "version": "0.30.17", 1820 - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 1821 - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 1822 - "dev": true, 1823 - "license": "MIT", 1824 - "dependencies": { 1825 - "@jridgewell/sourcemap-codec": "^1.5.0" 1826 - } 1827 - }, 1828 - "node_modules/mime": { 1829 - "version": "3.0.0", 1830 - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", 1831 - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", 1832 - "dev": true, 1833 - "license": "MIT", 1834 - "bin": { 1835 - "mime": "cli.js" 1836 - }, 1837 - "engines": { 1838 - "node": ">=10.0.0" 1839 - } 1840 - }, 1841 - "node_modules/miniflare": { 1842 - "version": "4.20250428.1", 1843 - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20250428.1.tgz", 1844 - "integrity": "sha512-M3qcJXjeAEimHrEeWXEhrJiC3YHB5M3QSqqK67pOTI+lHn0QyVG/2iFUjVJ/nv+i10uxeAEva8GRGeu+tKRCmQ==", 1845 - "dev": true, 1846 - "license": "MIT", 1847 - "dependencies": { 1848 - "@cspotcode/source-map-support": "0.8.1", 1849 - "acorn": "8.14.0", 1850 - "acorn-walk": "8.3.2", 1851 - "exit-hook": "2.2.1", 1852 - "glob-to-regexp": "0.4.1", 1853 - "stoppable": "1.1.0", 1854 - "undici": "^5.28.5", 1855 - "workerd": "1.20250428.0", 1856 - "ws": "8.18.0", 1857 - "youch": "3.3.4", 1858 - "zod": "3.22.3" 1859 - }, 1860 - "bin": { 1861 - "miniflare": "bootstrap.js" 1862 - }, 1863 - "engines": { 1864 - "node": ">=18.0.0" 1865 - } 1866 - }, 1867 - "node_modules/miniflare/node_modules/zod": { 1868 - "version": "3.22.3", 1869 - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", 1870 - "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", 1871 - "dev": true, 1872 - "license": "MIT", 1873 - "funding": { 1874 - "url": "https://github.com/sponsors/colinhacks" 1875 - } 1876 - }, 1877 - "node_modules/ms": { 1878 - "version": "2.1.3", 1879 - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1880 - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1881 - "dev": true, 1882 - "license": "MIT" 1883 - }, 1884 - "node_modules/mustache": { 1885 - "version": "4.2.0", 1886 - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", 1887 - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", 1888 - "dev": true, 1889 - "license": "MIT", 1890 - "bin": { 1891 - "mustache": "bin/mustache" 1892 - } 1893 - }, 1894 - "node_modules/nanoid": { 1895 - "version": "3.3.11", 1896 - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 1897 - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 1898 - "dev": true, 1899 - "funding": [ 1900 - { 1901 - "type": "github", 1902 - "url": "https://github.com/sponsors/ai" 1903 - } 1904 - ], 1905 - "license": "MIT", 1906 - "bin": { 1907 - "nanoid": "bin/nanoid.cjs" 1908 - }, 1909 - "engines": { 1910 - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1911 - } 1912 - }, 1913 - "node_modules/ohash": { 1914 - "version": "2.0.11", 1915 - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", 1916 - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", 1917 - "dev": true, 1918 - "license": "MIT" 1919 - }, 1920 - "node_modules/path-to-regexp": { 1921 - "version": "6.3.0", 1922 - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", 1923 - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", 1924 - "dev": true, 1925 - "license": "MIT" 1926 - }, 1927 - "node_modules/pathe": { 1928 - "version": "2.0.3", 1929 - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", 1930 - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", 1931 - "dev": true, 1932 - "license": "MIT" 1933 - }, 1934 - "node_modules/pathval": { 1935 - "version": "2.0.0", 1936 - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", 1937 - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", 1938 - "dev": true, 1939 - "license": "MIT", 1940 - "engines": { 1941 - "node": ">= 14.16" 1942 - } 1943 - }, 1944 - "node_modules/picocolors": { 1945 - "version": "1.1.1", 1946 - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1947 - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1948 - "dev": true, 1949 - "license": "ISC" 1950 - }, 1951 - "node_modules/picomatch": { 1952 - "version": "4.0.2", 1953 - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", 1954 - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", 1955 - "dev": true, 1956 - "license": "MIT", 1957 - "engines": { 1958 - "node": ">=12" 1959 - }, 1960 - "funding": { 1961 - "url": "https://github.com/sponsors/jonschlinkert" 1962 - } 1963 - }, 1964 - "node_modules/postcss": { 1965 - "version": "8.5.3", 1966 - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", 1967 - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", 1968 - "dev": true, 1969 - "funding": [ 1970 - { 1971 - "type": "opencollective", 1972 - "url": "https://opencollective.com/postcss/" 1973 - }, 1974 - { 1975 - "type": "tidelift", 1976 - "url": "https://tidelift.com/funding/github/npm/postcss" 1977 - }, 1978 - { 1979 - "type": "github", 1980 - "url": "https://github.com/sponsors/ai" 1981 - } 1982 - ], 1983 - "license": "MIT", 1984 - "dependencies": { 1985 - "nanoid": "^3.3.8", 1986 - "picocolors": "^1.1.1", 1987 - "source-map-js": "^1.2.1" 1988 - }, 1989 - "engines": { 1990 - "node": "^10 || ^12 || >=14" 1991 - } 1992 - }, 1993 - "node_modules/printable-characters": { 1994 - "version": "1.0.42", 1995 - "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", 1996 - "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", 1997 - "dev": true, 1998 - "license": "Unlicense" 1999 - }, 2000 - "node_modules/rollup": { 2001 - "version": "4.40.1", 2002 - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.1.tgz", 2003 - "integrity": "sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==", 2004 - "dev": true, 2005 - "license": "MIT", 2006 - "dependencies": { 2007 - "@types/estree": "1.0.7" 2008 - }, 2009 - "bin": { 2010 - "rollup": "dist/bin/rollup" 2011 - }, 2012 - "engines": { 2013 - "node": ">=18.0.0", 2014 - "npm": ">=8.0.0" 2015 - }, 2016 - "optionalDependencies": { 2017 - "@rollup/rollup-android-arm-eabi": "4.40.1", 2018 - "@rollup/rollup-android-arm64": "4.40.1", 2019 - "@rollup/rollup-darwin-arm64": "4.40.1", 2020 - "@rollup/rollup-darwin-x64": "4.40.1", 2021 - "@rollup/rollup-freebsd-arm64": "4.40.1", 2022 - "@rollup/rollup-freebsd-x64": "4.40.1", 2023 - "@rollup/rollup-linux-arm-gnueabihf": "4.40.1", 2024 - "@rollup/rollup-linux-arm-musleabihf": "4.40.1", 2025 - "@rollup/rollup-linux-arm64-gnu": "4.40.1", 2026 - "@rollup/rollup-linux-arm64-musl": "4.40.1", 2027 - "@rollup/rollup-linux-loongarch64-gnu": "4.40.1", 2028 - "@rollup/rollup-linux-powerpc64le-gnu": "4.40.1", 2029 - "@rollup/rollup-linux-riscv64-gnu": "4.40.1", 2030 - "@rollup/rollup-linux-riscv64-musl": "4.40.1", 2031 - "@rollup/rollup-linux-s390x-gnu": "4.40.1", 2032 - "@rollup/rollup-linux-x64-gnu": "4.40.1", 2033 - "@rollup/rollup-linux-x64-musl": "4.40.1", 2034 - "@rollup/rollup-win32-arm64-msvc": "4.40.1", 2035 - "@rollup/rollup-win32-ia32-msvc": "4.40.1", 2036 - "@rollup/rollup-win32-x64-msvc": "4.40.1", 2037 - "fsevents": "~2.3.2" 2038 - } 2039 - }, 2040 - "node_modules/semver": { 2041 - "version": "7.7.1", 2042 - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", 2043 - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", 2044 - "dev": true, 2045 - "license": "ISC", 2046 - "bin": { 2047 - "semver": "bin/semver.js" 2048 - }, 2049 - "engines": { 2050 - "node": ">=10" 2051 - } 2052 - }, 2053 - "node_modules/sharp": { 2054 - "version": "0.33.5", 2055 - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", 2056 - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", 2057 - "dev": true, 2058 - "hasInstallScript": true, 2059 - "license": "Apache-2.0", 2060 - "optional": true, 2061 - "dependencies": { 2062 - "color": "^4.2.3", 2063 - "detect-libc": "^2.0.3", 2064 - "semver": "^7.6.3" 2065 - }, 2066 - "engines": { 2067 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 2068 - }, 2069 - "funding": { 2070 - "url": "https://opencollective.com/libvips" 2071 - }, 2072 - "optionalDependencies": { 2073 - "@img/sharp-darwin-arm64": "0.33.5", 2074 - "@img/sharp-darwin-x64": "0.33.5", 2075 - "@img/sharp-libvips-darwin-arm64": "1.0.4", 2076 - "@img/sharp-libvips-darwin-x64": "1.0.4", 2077 - "@img/sharp-libvips-linux-arm": "1.0.5", 2078 - "@img/sharp-libvips-linux-arm64": "1.0.4", 2079 - "@img/sharp-libvips-linux-s390x": "1.0.4", 2080 - "@img/sharp-libvips-linux-x64": "1.0.4", 2081 - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", 2082 - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", 2083 - "@img/sharp-linux-arm": "0.33.5", 2084 - "@img/sharp-linux-arm64": "0.33.5", 2085 - "@img/sharp-linux-s390x": "0.33.5", 2086 - "@img/sharp-linux-x64": "0.33.5", 2087 - "@img/sharp-linuxmusl-arm64": "0.33.5", 2088 - "@img/sharp-linuxmusl-x64": "0.33.5", 2089 - "@img/sharp-wasm32": "0.33.5", 2090 - "@img/sharp-win32-ia32": "0.33.5", 2091 - "@img/sharp-win32-x64": "0.33.5" 2092 - } 2093 - }, 2094 - "node_modules/siginfo": { 2095 - "version": "2.0.0", 2096 - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", 2097 - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", 2098 - "dev": true, 2099 - "license": "ISC" 2100 - }, 2101 - "node_modules/simple-swizzle": { 2102 - "version": "0.2.2", 2103 - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", 2104 - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", 2105 - "dev": true, 2106 - "license": "MIT", 2107 - "optional": true, 2108 - "dependencies": { 2109 - "is-arrayish": "^0.3.1" 2110 - } 2111 - }, 2112 - "node_modules/source-map": { 2113 - "version": "0.6.1", 2114 - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2115 - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2116 - "dev": true, 2117 - "license": "BSD-3-Clause", 2118 - "engines": { 2119 - "node": ">=0.10.0" 2120 - } 2121 - }, 2122 - "node_modules/source-map-js": { 2123 - "version": "1.2.1", 2124 - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 2125 - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 2126 - "dev": true, 2127 - "license": "BSD-3-Clause", 2128 - "engines": { 2129 - "node": ">=0.10.0" 2130 - } 2131 - }, 2132 - "node_modules/stackback": { 2133 - "version": "0.0.2", 2134 - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", 2135 - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", 2136 - "dev": true, 2137 - "license": "MIT" 2138 - }, 2139 - "node_modules/stacktracey": { 2140 - "version": "2.1.8", 2141 - "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", 2142 - "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", 2143 - "dev": true, 2144 - "license": "Unlicense", 2145 - "dependencies": { 2146 - "as-table": "^1.0.36", 2147 - "get-source": "^2.0.12" 2148 - } 2149 - }, 2150 - "node_modules/std-env": { 2151 - "version": "3.9.0", 2152 - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", 2153 - "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", 2154 - "dev": true, 2155 - "license": "MIT" 2156 - }, 2157 - "node_modules/stoppable": { 2158 - "version": "1.1.0", 2159 - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", 2160 - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", 2161 - "dev": true, 2162 - "license": "MIT", 2163 - "engines": { 2164 - "node": ">=4", 2165 - "npm": ">=6" 2166 - } 2167 - }, 2168 - "node_modules/tinybench": { 2169 - "version": "2.9.0", 2170 - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", 2171 - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", 2172 - "dev": true, 2173 - "license": "MIT" 2174 - }, 2175 - "node_modules/tinyexec": { 2176 - "version": "0.3.2", 2177 - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", 2178 - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", 2179 - "dev": true, 2180 - "license": "MIT" 2181 - }, 2182 - "node_modules/tinyglobby": { 2183 - "version": "0.2.13", 2184 - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", 2185 - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", 2186 - "dev": true, 2187 - "license": "MIT", 2188 - "dependencies": { 2189 - "fdir": "^6.4.4", 2190 - "picomatch": "^4.0.2" 2191 - }, 2192 - "engines": { 2193 - "node": ">=12.0.0" 2194 - }, 2195 - "funding": { 2196 - "url": "https://github.com/sponsors/SuperchupuDev" 2197 - } 2198 - }, 2199 - "node_modules/tinypool": { 2200 - "version": "1.0.2", 2201 - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", 2202 - "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", 2203 - "dev": true, 2204 - "license": "MIT", 2205 - "engines": { 2206 - "node": "^18.0.0 || >=20.0.0" 2207 - } 2208 - }, 2209 - "node_modules/tinyrainbow": { 2210 - "version": "2.0.0", 2211 - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", 2212 - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", 2213 - "dev": true, 2214 - "license": "MIT", 2215 - "engines": { 2216 - "node": ">=14.0.0" 2217 - } 2218 - }, 2219 - "node_modules/tinyspy": { 2220 - "version": "3.0.2", 2221 - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", 2222 - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", 2223 - "dev": true, 2224 - "license": "MIT", 2225 - "engines": { 2226 - "node": ">=14.0.0" 2227 - } 2228 - }, 2229 - "node_modules/tslib": { 2230 - "version": "2.8.1", 2231 - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 2232 - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 2233 - "dev": true, 2234 - "license": "0BSD", 2235 - "optional": true 2236 - }, 2237 - "node_modules/ufo": { 2238 - "version": "1.6.1", 2239 - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", 2240 - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", 2241 - "dev": true, 2242 - "license": "MIT" 2243 - }, 2244 - "node_modules/undici": { 2245 - "version": "5.29.0", 2246 - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", 2247 - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", 2248 - "dev": true, 2249 - "license": "MIT", 2250 - "dependencies": { 2251 - "@fastify/busboy": "^2.0.0" 2252 - }, 2253 - "engines": { 2254 - "node": ">=14.0" 2255 - } 2256 - }, 2257 - "node_modules/unenv": { 2258 - "version": "2.0.0-rc.15", 2259 - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.15.tgz", 2260 - "integrity": "sha512-J/rEIZU8w6FOfLNz/hNKsnY+fFHWnu9MH4yRbSZF3xbbGHovcetXPs7sD+9p8L6CeNC//I9bhRYAOsBt2u7/OA==", 2261 - "dev": true, 2262 - "license": "MIT", 2263 - "dependencies": { 2264 - "defu": "^6.1.4", 2265 - "exsolve": "^1.0.4", 2266 - "ohash": "^2.0.11", 2267 - "pathe": "^2.0.3", 2268 - "ufo": "^1.5.4" 2269 - } 2270 - }, 2271 - "node_modules/vite": { 2272 - "version": "6.3.4", 2273 - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.4.tgz", 2274 - "integrity": "sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==", 2275 - "dev": true, 2276 - "license": "MIT", 2277 - "dependencies": { 2278 - "esbuild": "^0.25.0", 2279 - "fdir": "^6.4.4", 2280 - "picomatch": "^4.0.2", 2281 - "postcss": "^8.5.3", 2282 - "rollup": "^4.34.9", 2283 - "tinyglobby": "^0.2.13" 2284 - }, 2285 - "bin": { 2286 - "vite": "bin/vite.js" 2287 - }, 2288 - "engines": { 2289 - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2290 - }, 2291 - "funding": { 2292 - "url": "https://github.com/vitejs/vite?sponsor=1" 2293 - }, 2294 - "optionalDependencies": { 2295 - "fsevents": "~2.3.3" 2296 - }, 2297 - "peerDependencies": { 2298 - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2299 - "jiti": ">=1.21.0", 2300 - "less": "*", 2301 - "lightningcss": "^1.21.0", 2302 - "sass": "*", 2303 - "sass-embedded": "*", 2304 - "stylus": "*", 2305 - "sugarss": "*", 2306 - "terser": "^5.16.0", 2307 - "tsx": "^4.8.1", 2308 - "yaml": "^2.4.2" 2309 - }, 2310 - "peerDependenciesMeta": { 2311 - "@types/node": { 2312 - "optional": true 2313 - }, 2314 - "jiti": { 2315 - "optional": true 2316 - }, 2317 - "less": { 2318 - "optional": true 2319 - }, 2320 - "lightningcss": { 2321 - "optional": true 2322 - }, 2323 - "sass": { 2324 - "optional": true 2325 - }, 2326 - "sass-embedded": { 2327 - "optional": true 2328 - }, 2329 - "stylus": { 2330 - "optional": true 2331 - }, 2332 - "sugarss": { 2333 - "optional": true 2334 - }, 2335 - "terser": { 2336 - "optional": true 2337 - }, 2338 - "tsx": { 2339 - "optional": true 2340 - }, 2341 - "yaml": { 2342 - "optional": true 2343 - } 2344 - } 2345 - }, 2346 - "node_modules/vite-node": { 2347 - "version": "3.0.9", 2348 - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", 2349 - "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", 2350 - "dev": true, 2351 - "license": "MIT", 2352 - "dependencies": { 2353 - "cac": "^6.7.14", 2354 - "debug": "^4.4.0", 2355 - "es-module-lexer": "^1.6.0", 2356 - "pathe": "^2.0.3", 2357 - "vite": "^5.0.0 || ^6.0.0" 2358 - }, 2359 - "bin": { 2360 - "vite-node": "vite-node.mjs" 2361 - }, 2362 - "engines": { 2363 - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2364 - }, 2365 - "funding": { 2366 - "url": "https://opencollective.com/vitest" 2367 - } 2368 - }, 2369 - "node_modules/vitest": { 2370 - "version": "3.0.9", 2371 - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", 2372 - "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", 2373 - "dev": true, 2374 - "license": "MIT", 2375 - "dependencies": { 2376 - "@vitest/expect": "3.0.9", 2377 - "@vitest/mocker": "3.0.9", 2378 - "@vitest/pretty-format": "^3.0.9", 2379 - "@vitest/runner": "3.0.9", 2380 - "@vitest/snapshot": "3.0.9", 2381 - "@vitest/spy": "3.0.9", 2382 - "@vitest/utils": "3.0.9", 2383 - "chai": "^5.2.0", 2384 - "debug": "^4.4.0", 2385 - "expect-type": "^1.1.0", 2386 - "magic-string": "^0.30.17", 2387 - "pathe": "^2.0.3", 2388 - "std-env": "^3.8.0", 2389 - "tinybench": "^2.9.0", 2390 - "tinyexec": "^0.3.2", 2391 - "tinypool": "^1.0.2", 2392 - "tinyrainbow": "^2.0.0", 2393 - "vite": "^5.0.0 || ^6.0.0", 2394 - "vite-node": "3.0.9", 2395 - "why-is-node-running": "^2.3.0" 2396 - }, 2397 - "bin": { 2398 - "vitest": "vitest.mjs" 2399 - }, 2400 - "engines": { 2401 - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2402 - }, 2403 - "funding": { 2404 - "url": "https://opencollective.com/vitest" 2405 - }, 2406 - "peerDependencies": { 2407 - "@edge-runtime/vm": "*", 2408 - "@types/debug": "^4.1.12", 2409 - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2410 - "@vitest/browser": "3.0.9", 2411 - "@vitest/ui": "3.0.9", 2412 - "happy-dom": "*", 2413 - "jsdom": "*" 2414 - }, 2415 - "peerDependenciesMeta": { 2416 - "@edge-runtime/vm": { 2417 - "optional": true 2418 - }, 2419 - "@types/debug": { 2420 - "optional": true 2421 - }, 2422 - "@types/node": { 2423 - "optional": true 2424 - }, 2425 - "@vitest/browser": { 2426 - "optional": true 2427 - }, 2428 - "@vitest/ui": { 2429 - "optional": true 2430 - }, 2431 - "happy-dom": { 2432 - "optional": true 2433 - }, 2434 - "jsdom": { 2435 - "optional": true 2436 - } 2437 - } 2438 - }, 2439 - "node_modules/why-is-node-running": { 2440 - "version": "2.3.0", 2441 - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", 2442 - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", 2443 - "dev": true, 2444 - "license": "MIT", 2445 - "dependencies": { 2446 - "siginfo": "^2.0.0", 2447 - "stackback": "0.0.2" 2448 - }, 2449 - "bin": { 2450 - "why-is-node-running": "cli.js" 2451 - }, 2452 - "engines": { 2453 - "node": ">=8" 2454 - } 2455 - }, 2456 - "node_modules/workerd": { 2457 - "version": "1.20250428.0", 2458 - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250428.0.tgz", 2459 - "integrity": "sha512-JJNWkHkwPQKQdvtM9UORijgYdcdJsihA4SfYjwh02IUQsdMyZ9jizV1sX9yWi9B9ptlohTW8UNHJEATuphGgdg==", 2460 - "dev": true, 2461 - "hasInstallScript": true, 2462 - "license": "Apache-2.0", 2463 - "bin": { 2464 - "workerd": "bin/workerd" 2465 - }, 2466 - "engines": { 2467 - "node": ">=16" 2468 - }, 2469 - "optionalDependencies": { 2470 - "@cloudflare/workerd-darwin-64": "1.20250428.0", 2471 - "@cloudflare/workerd-darwin-arm64": "1.20250428.0", 2472 - "@cloudflare/workerd-linux-64": "1.20250428.0", 2473 - "@cloudflare/workerd-linux-arm64": "1.20250428.0", 2474 - "@cloudflare/workerd-windows-64": "1.20250428.0" 2475 - } 2476 - }, 2477 - "node_modules/wrangler": { 2478 - "version": "4.14.1", 2479 - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.14.1.tgz", 2480 - "integrity": "sha512-EU7IThP7i68TBftJJSveogvWZ5k/WRijcJh3UclDWiWWhDZTPbL6LOJEFhHKqFzHOaC4Y2Aewt48rfTz0e7oCw==", 2481 - "dev": true, 2482 - "license": "MIT OR Apache-2.0", 2483 - "dependencies": { 2484 - "@cloudflare/kv-asset-handler": "0.4.0", 2485 - "@cloudflare/unenv-preset": "2.3.1", 2486 - "blake3-wasm": "2.1.5", 2487 - "esbuild": "0.25.2", 2488 - "miniflare": "4.20250428.1", 2489 - "path-to-regexp": "6.3.0", 2490 - "unenv": "2.0.0-rc.15", 2491 - "workerd": "1.20250428.0" 2492 - }, 2493 - "bin": { 2494 - "wrangler": "bin/wrangler.js", 2495 - "wrangler2": "bin/wrangler.js" 2496 - }, 2497 - "engines": { 2498 - "node": ">=18.0.0" 2499 - }, 2500 - "optionalDependencies": { 2501 - "fsevents": "~2.3.2", 2502 - "sharp": "^0.33.5" 2503 - }, 2504 - "peerDependencies": { 2505 - "@cloudflare/workers-types": "^4.20250428.0" 2506 - }, 2507 - "peerDependenciesMeta": { 2508 - "@cloudflare/workers-types": { 2509 - "optional": true 2510 - } 2511 - } 2512 - }, 2513 - "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": { 2514 - "version": "0.25.2", 2515 - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", 2516 - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", 2517 - "cpu": [ 2518 - "ppc64" 2519 - ], 2520 - "dev": true, 2521 - "license": "MIT", 2522 - "optional": true, 2523 - "os": [ 2524 - "aix" 2525 - ], 2526 - "engines": { 2527 - "node": ">=18" 2528 - } 2529 - }, 2530 - "node_modules/wrangler/node_modules/@esbuild/android-arm": { 2531 - "version": "0.25.2", 2532 - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", 2533 - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", 2534 - "cpu": [ 2535 - "arm" 2536 - ], 2537 - "dev": true, 2538 - "license": "MIT", 2539 - "optional": true, 2540 - "os": [ 2541 - "android" 2542 - ], 2543 - "engines": { 2544 - "node": ">=18" 2545 - } 2546 - }, 2547 - "node_modules/wrangler/node_modules/@esbuild/android-arm64": { 2548 - "version": "0.25.2", 2549 - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", 2550 - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", 2551 - "cpu": [ 2552 - "arm64" 2553 - ], 2554 - "dev": true, 2555 - "license": "MIT", 2556 - "optional": true, 2557 - "os": [ 2558 - "android" 2559 - ], 2560 - "engines": { 2561 - "node": ">=18" 2562 - } 2563 - }, 2564 - "node_modules/wrangler/node_modules/@esbuild/android-x64": { 2565 - "version": "0.25.2", 2566 - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", 2567 - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", 2568 - "cpu": [ 2569 - "x64" 2570 - ], 2571 - "dev": true, 2572 - "license": "MIT", 2573 - "optional": true, 2574 - "os": [ 2575 - "android" 2576 - ], 2577 - "engines": { 2578 - "node": ">=18" 2579 - } 2580 - }, 2581 - "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { 2582 - "version": "0.25.2", 2583 - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", 2584 - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", 2585 - "cpu": [ 2586 - "arm64" 2587 - ], 2588 - "dev": true, 2589 - "license": "MIT", 2590 - "optional": true, 2591 - "os": [ 2592 - "darwin" 2593 - ], 2594 - "engines": { 2595 - "node": ">=18" 2596 - } 2597 - }, 2598 - "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { 2599 - "version": "0.25.2", 2600 - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", 2601 - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", 2602 - "cpu": [ 2603 - "x64" 2604 - ], 2605 - "dev": true, 2606 - "license": "MIT", 2607 - "optional": true, 2608 - "os": [ 2609 - "darwin" 2610 - ], 2611 - "engines": { 2612 - "node": ">=18" 2613 - } 2614 - }, 2615 - "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { 2616 - "version": "0.25.2", 2617 - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", 2618 - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", 2619 - "cpu": [ 2620 - "arm64" 2621 - ], 2622 - "dev": true, 2623 - "license": "MIT", 2624 - "optional": true, 2625 - "os": [ 2626 - "freebsd" 2627 - ], 2628 - "engines": { 2629 - "node": ">=18" 2630 - } 2631 - }, 2632 - "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { 2633 - "version": "0.25.2", 2634 - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", 2635 - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", 2636 - "cpu": [ 2637 - "x64" 2638 - ], 2639 - "dev": true, 2640 - "license": "MIT", 2641 - "optional": true, 2642 - "os": [ 2643 - "freebsd" 2644 - ], 2645 - "engines": { 2646 - "node": ">=18" 2647 - } 2648 - }, 2649 - "node_modules/wrangler/node_modules/@esbuild/linux-arm": { 2650 - "version": "0.25.2", 2651 - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", 2652 - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", 2653 - "cpu": [ 2654 - "arm" 2655 - ], 2656 - "dev": true, 2657 - "license": "MIT", 2658 - "optional": true, 2659 - "os": [ 2660 - "linux" 2661 - ], 2662 - "engines": { 2663 - "node": ">=18" 2664 - } 2665 - }, 2666 - "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { 2667 - "version": "0.25.2", 2668 - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", 2669 - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", 2670 - "cpu": [ 2671 - "arm64" 2672 - ], 2673 - "dev": true, 2674 - "license": "MIT", 2675 - "optional": true, 2676 - "os": [ 2677 - "linux" 2678 - ], 2679 - "engines": { 2680 - "node": ">=18" 2681 - } 2682 - }, 2683 - "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { 2684 - "version": "0.25.2", 2685 - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", 2686 - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", 2687 - "cpu": [ 2688 - "ia32" 2689 - ], 2690 - "dev": true, 2691 - "license": "MIT", 2692 - "optional": true, 2693 - "os": [ 2694 - "linux" 2695 - ], 2696 - "engines": { 2697 - "node": ">=18" 2698 - } 2699 - }, 2700 - "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { 2701 - "version": "0.25.2", 2702 - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", 2703 - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", 2704 - "cpu": [ 2705 - "loong64" 2706 - ], 2707 - "dev": true, 2708 - "license": "MIT", 2709 - "optional": true, 2710 - "os": [ 2711 - "linux" 2712 - ], 2713 - "engines": { 2714 - "node": ">=18" 2715 - } 2716 - }, 2717 - "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { 2718 - "version": "0.25.2", 2719 - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", 2720 - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", 2721 - "cpu": [ 2722 - "mips64el" 2723 - ], 2724 - "dev": true, 2725 - "license": "MIT", 2726 - "optional": true, 2727 - "os": [ 2728 - "linux" 2729 - ], 2730 - "engines": { 2731 - "node": ">=18" 2732 - } 2733 - }, 2734 - "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { 2735 - "version": "0.25.2", 2736 - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", 2737 - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", 2738 - "cpu": [ 2739 - "ppc64" 2740 - ], 2741 - "dev": true, 2742 - "license": "MIT", 2743 - "optional": true, 2744 - "os": [ 2745 - "linux" 2746 - ], 2747 - "engines": { 2748 - "node": ">=18" 2749 - } 2750 - }, 2751 - "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { 2752 - "version": "0.25.2", 2753 - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", 2754 - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", 2755 - "cpu": [ 2756 - "riscv64" 2757 - ], 2758 - "dev": true, 2759 - "license": "MIT", 2760 - "optional": true, 2761 - "os": [ 2762 - "linux" 2763 - ], 2764 - "engines": { 2765 - "node": ">=18" 2766 - } 2767 - }, 2768 - "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { 2769 - "version": "0.25.2", 2770 - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", 2771 - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", 2772 - "cpu": [ 2773 - "s390x" 2774 - ], 2775 - "dev": true, 2776 - "license": "MIT", 2777 - "optional": true, 2778 - "os": [ 2779 - "linux" 2780 - ], 2781 - "engines": { 2782 - "node": ">=18" 2783 - } 2784 - }, 2785 - "node_modules/wrangler/node_modules/@esbuild/linux-x64": { 2786 - "version": "0.25.2", 2787 - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", 2788 - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", 2789 - "cpu": [ 2790 - "x64" 2791 - ], 2792 - "dev": true, 2793 - "license": "MIT", 2794 - "optional": true, 2795 - "os": [ 2796 - "linux" 2797 - ], 2798 - "engines": { 2799 - "node": ">=18" 2800 - } 2801 - }, 2802 - "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": { 2803 - "version": "0.25.2", 2804 - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", 2805 - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", 2806 - "cpu": [ 2807 - "arm64" 2808 - ], 2809 - "dev": true, 2810 - "license": "MIT", 2811 - "optional": true, 2812 - "os": [ 2813 - "netbsd" 2814 - ], 2815 - "engines": { 2816 - "node": ">=18" 2817 - } 2818 - }, 2819 - "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { 2820 - "version": "0.25.2", 2821 - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", 2822 - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", 2823 - "cpu": [ 2824 - "x64" 2825 - ], 2826 - "dev": true, 2827 - "license": "MIT", 2828 - "optional": true, 2829 - "os": [ 2830 - "netbsd" 2831 - ], 2832 - "engines": { 2833 - "node": ">=18" 2834 - } 2835 - }, 2836 - "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": { 2837 - "version": "0.25.2", 2838 - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", 2839 - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", 2840 - "cpu": [ 2841 - "arm64" 2842 - ], 2843 - "dev": true, 2844 - "license": "MIT", 2845 - "optional": true, 2846 - "os": [ 2847 - "openbsd" 2848 - ], 2849 - "engines": { 2850 - "node": ">=18" 2851 - } 2852 - }, 2853 - "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { 2854 - "version": "0.25.2", 2855 - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", 2856 - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", 2857 - "cpu": [ 2858 - "x64" 2859 - ], 2860 - "dev": true, 2861 - "license": "MIT", 2862 - "optional": true, 2863 - "os": [ 2864 - "openbsd" 2865 - ], 2866 - "engines": { 2867 - "node": ">=18" 2868 - } 2869 - }, 2870 - "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { 2871 - "version": "0.25.2", 2872 - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", 2873 - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", 2874 - "cpu": [ 2875 - "x64" 2876 - ], 2877 - "dev": true, 2878 - "license": "MIT", 2879 - "optional": true, 2880 - "os": [ 2881 - "sunos" 2882 - ], 2883 - "engines": { 2884 - "node": ">=18" 2885 - } 2886 - }, 2887 - "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { 2888 - "version": "0.25.2", 2889 - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", 2890 - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", 2891 - "cpu": [ 2892 - "arm64" 2893 - ], 2894 - "dev": true, 2895 - "license": "MIT", 2896 - "optional": true, 2897 - "os": [ 2898 - "win32" 2899 - ], 2900 - "engines": { 2901 - "node": ">=18" 2902 - } 2903 - }, 2904 - "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { 2905 - "version": "0.25.2", 2906 - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", 2907 - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", 2908 - "cpu": [ 2909 - "ia32" 2910 - ], 2911 - "dev": true, 2912 - "license": "MIT", 2913 - "optional": true, 2914 - "os": [ 2915 - "win32" 2916 - ], 2917 - "engines": { 2918 - "node": ">=18" 2919 - } 2920 - }, 2921 - "node_modules/wrangler/node_modules/@esbuild/win32-x64": { 2922 - "version": "0.25.2", 2923 - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", 2924 - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", 2925 - "cpu": [ 2926 - "x64" 2927 - ], 2928 - "dev": true, 2929 - "license": "MIT", 2930 - "optional": true, 2931 - "os": [ 2932 - "win32" 2933 - ], 2934 - "engines": { 2935 - "node": ">=18" 2936 - } 2937 - }, 2938 - "node_modules/wrangler/node_modules/esbuild": { 2939 - "version": "0.25.2", 2940 - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", 2941 - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", 2942 - "dev": true, 2943 - "hasInstallScript": true, 2944 - "license": "MIT", 2945 - "bin": { 2946 - "esbuild": "bin/esbuild" 2947 - }, 2948 - "engines": { 2949 - "node": ">=18" 2950 - }, 2951 - "optionalDependencies": { 2952 - "@esbuild/aix-ppc64": "0.25.2", 2953 - "@esbuild/android-arm": "0.25.2", 2954 - "@esbuild/android-arm64": "0.25.2", 2955 - "@esbuild/android-x64": "0.25.2", 2956 - "@esbuild/darwin-arm64": "0.25.2", 2957 - "@esbuild/darwin-x64": "0.25.2", 2958 - "@esbuild/freebsd-arm64": "0.25.2", 2959 - "@esbuild/freebsd-x64": "0.25.2", 2960 - "@esbuild/linux-arm": "0.25.2", 2961 - "@esbuild/linux-arm64": "0.25.2", 2962 - "@esbuild/linux-ia32": "0.25.2", 2963 - "@esbuild/linux-loong64": "0.25.2", 2964 - "@esbuild/linux-mips64el": "0.25.2", 2965 - "@esbuild/linux-ppc64": "0.25.2", 2966 - "@esbuild/linux-riscv64": "0.25.2", 2967 - "@esbuild/linux-s390x": "0.25.2", 2968 - "@esbuild/linux-x64": "0.25.2", 2969 - "@esbuild/netbsd-arm64": "0.25.2", 2970 - "@esbuild/netbsd-x64": "0.25.2", 2971 - "@esbuild/openbsd-arm64": "0.25.2", 2972 - "@esbuild/openbsd-x64": "0.25.2", 2973 - "@esbuild/sunos-x64": "0.25.2", 2974 - "@esbuild/win32-arm64": "0.25.2", 2975 - "@esbuild/win32-ia32": "0.25.2", 2976 - "@esbuild/win32-x64": "0.25.2" 2977 - } 2978 - }, 2979 - "node_modules/ws": { 2980 - "version": "8.18.0", 2981 - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", 2982 - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", 2983 - "dev": true, 2984 - "license": "MIT", 2985 - "engines": { 2986 - "node": ">=10.0.0" 2987 - }, 2988 - "peerDependencies": { 2989 - "bufferutil": "^4.0.1", 2990 - "utf-8-validate": ">=5.0.2" 2991 - }, 2992 - "peerDependenciesMeta": { 2993 - "bufferutil": { 2994 - "optional": true 2995 - }, 2996 - "utf-8-validate": { 2997 - "optional": true 2998 - } 2999 - } 3000 - }, 3001 - "node_modules/youch": { 3002 - "version": "3.3.4", 3003 - "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.4.tgz", 3004 - "integrity": "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==", 3005 - "dev": true, 3006 - "license": "MIT", 3007 - "dependencies": { 3008 - "cookie": "^0.7.1", 3009 - "mustache": "^4.2.0", 3010 - "stacktracey": "^2.1.8" 3011 - } 3012 - }, 3013 - "node_modules/zod": { 3014 - "version": "3.24.3", 3015 - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz", 3016 - "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==", 3017 - "dev": true, 3018 - "license": "MIT", 3019 - "funding": { 3020 - "url": "https://github.com/sponsors/colinhacks" 3021 - } 3022 - } 3023 - } 2 + "name": "avatar", 3 + "version": "0.0.0", 4 + "lockfileVersion": 3, 5 + "requires": true, 6 + "packages": { 7 + "": { 8 + "name": "avatar", 9 + "version": "0.0.0", 10 + "dependencies": { 11 + "@atcute/identity-resolver": "^1.2.2" 12 + }, 13 + "devDependencies": { 14 + "@cloudflare/vitest-pool-workers": "^0.8.19", 15 + "vitest": "~3.0.7", 16 + "wrangler": "^4.14.1" 17 + } 18 + }, 19 + "node_modules/@atcute/identity": { 20 + "version": "1.1.3", 21 + "resolved": "https://registry.npmjs.org/@atcute/identity/-/identity-1.1.3.tgz", 22 + "integrity": "sha512-oIqPoI8TwWeQxvcLmFEZLdN2XdWcaLVtlm8pNk0E72As9HNzzD9pwKPrLr3rmTLRIoULPPFmq9iFNsTeCIU9ng==", 23 + "license": "0BSD", 24 + "peer": true, 25 + "dependencies": { 26 + "@atcute/lexicons": "^1.2.4", 27 + "@badrap/valita": "^0.4.6" 28 + } 29 + }, 30 + "node_modules/@atcute/identity-resolver": { 31 + "version": "1.2.2", 32 + "resolved": "https://registry.npmjs.org/@atcute/identity-resolver/-/identity-resolver-1.2.2.tgz", 33 + "integrity": "sha512-eUh/UH4bFvuXS0X7epYCeJC/kj4rbBXfSRumLEH4smMVwNOgTo7cL/0Srty+P/qVPoZEyXdfEbS0PHJyzoXmHw==", 34 + "license": "0BSD", 35 + "dependencies": { 36 + "@atcute/lexicons": "^1.2.6", 37 + "@atcute/util-fetch": "^1.0.5", 38 + "@badrap/valita": "^0.4.6" 39 + }, 40 + "peerDependencies": { 41 + "@atcute/identity": "^1.0.0" 42 + } 43 + }, 44 + "node_modules/@atcute/lexicons": { 45 + "version": "1.2.6", 46 + "resolved": "https://registry.npmjs.org/@atcute/lexicons/-/lexicons-1.2.6.tgz", 47 + "integrity": "sha512-s76UQd8D+XmHIzrjD9CJ9SOOeeLPHc+sMmcj7UFakAW/dDFXc579fcRdRfuUKvXBL5v1Gs2VgDdlh/IvvQZAwA==", 48 + "license": "0BSD", 49 + "dependencies": { 50 + "@atcute/uint8array": "^1.0.6", 51 + "@atcute/util-text": "^0.0.1", 52 + "@standard-schema/spec": "^1.1.0", 53 + "esm-env": "^1.2.2" 54 + } 55 + }, 56 + "node_modules/@atcute/uint8array": { 57 + "version": "1.0.6", 58 + "resolved": "https://registry.npmjs.org/@atcute/uint8array/-/uint8array-1.0.6.tgz", 59 + "integrity": "sha512-ucfRBQc7BFT8n9eCyGOzDHEMKF/nZwhS2pPao4Xtab1ML3HdFYcX2DM1tadCzas85QTGxHe5urnUAAcNKGRi9A==", 60 + "license": "0BSD" 61 + }, 62 + "node_modules/@atcute/util-fetch": { 63 + "version": "1.0.5", 64 + "resolved": "https://registry.npmjs.org/@atcute/util-fetch/-/util-fetch-1.0.5.tgz", 65 + "integrity": "sha512-qjHj01BGxjSjIFdPiAjSARnodJIIyKxnCMMEcXMESo9TAyND6XZQqrie5fia+LlYWVXdpsTds8uFQwc9jdKTig==", 66 + "license": "0BSD", 67 + "dependencies": { 68 + "@badrap/valita": "^0.4.6" 69 + } 70 + }, 71 + "node_modules/@atcute/util-text": { 72 + "version": "0.0.1", 73 + "resolved": "https://registry.npmjs.org/@atcute/util-text/-/util-text-0.0.1.tgz", 74 + "integrity": "sha512-t1KZqvn0AYy+h2KcJyHnKF9aEqfRfMUmyY8j1ELtAEIgqN9CxINAjxnoRCJIFUlvWzb+oY3uElQL/Vyk3yss0g==", 75 + "license": "0BSD", 76 + "dependencies": { 77 + "unicode-segmenter": "^0.14.4" 78 + } 79 + }, 80 + "node_modules/@badrap/valita": { 81 + "version": "0.4.6", 82 + "resolved": "https://registry.npmjs.org/@badrap/valita/-/valita-0.4.6.tgz", 83 + "integrity": "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==", 84 + "license": "MIT", 85 + "engines": { 86 + "node": ">= 18" 87 + } 88 + }, 89 + "node_modules/@cloudflare/kv-asset-handler": { 90 + "version": "0.4.0", 91 + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", 92 + "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", 93 + "dev": true, 94 + "license": "MIT OR Apache-2.0", 95 + "dependencies": { 96 + "mime": "^3.0.0" 97 + }, 98 + "engines": { 99 + "node": ">=18.0.0" 100 + } 101 + }, 102 + "node_modules/@cloudflare/unenv-preset": { 103 + "version": "2.3.1", 104 + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.3.1.tgz", 105 + "integrity": "sha512-Xq57Qd+ADpt6hibcVBO0uLG9zzRgyRhfCUgBT9s+g3+3Ivg5zDyVgLFy40ES1VdNcu8rPNSivm9A+kGP5IVaPg==", 106 + "dev": true, 107 + "license": "MIT OR Apache-2.0", 108 + "peerDependencies": { 109 + "unenv": "2.0.0-rc.15", 110 + "workerd": "^1.20250320.0" 111 + }, 112 + "peerDependenciesMeta": { 113 + "workerd": { 114 + "optional": true 115 + } 116 + } 117 + }, 118 + "node_modules/@cloudflare/vitest-pool-workers": { 119 + "version": "0.8.24", 120 + "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.8.24.tgz", 121 + "integrity": "sha512-wT2PABJQ9YLYWrVu4CRZOjvmjHkdbMyLTZPU9n/7JEMM3pgG8dY41F1Rj31UsXRQaXX39A/CTPGlk58dcMUysA==", 122 + "dev": true, 123 + "license": "MIT", 124 + "dependencies": { 125 + "birpc": "0.2.14", 126 + "cjs-module-lexer": "^1.2.3", 127 + "devalue": "^4.3.0", 128 + "miniflare": "4.20250428.1", 129 + "semver": "^7.7.1", 130 + "wrangler": "4.14.1", 131 + "zod": "^3.22.3" 132 + }, 133 + "peerDependencies": { 134 + "@vitest/runner": "2.0.x - 3.1.x", 135 + "@vitest/snapshot": "2.0.x - 3.1.x", 136 + "vitest": "2.0.x - 3.1.x" 137 + } 138 + }, 139 + "node_modules/@cloudflare/workerd-darwin-64": { 140 + "version": "1.20250428.0", 141 + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250428.0.tgz", 142 + "integrity": "sha512-6nVe9oV4Hdec6ctzMtW80TiDvNTd2oFPi3VsKqSDVaJSJbL+4b6seyJ7G/UEPI+si6JhHBSLV2/9lNXNGLjClA==", 143 + "cpu": [ 144 + "x64" 145 + ], 146 + "dev": true, 147 + "license": "Apache-2.0", 148 + "optional": true, 149 + "os": [ 150 + "darwin" 151 + ], 152 + "engines": { 153 + "node": ">=16" 154 + } 155 + }, 156 + "node_modules/@cloudflare/workerd-darwin-arm64": { 157 + "version": "1.20250428.0", 158 + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250428.0.tgz", 159 + "integrity": "sha512-/TB7bh7SIJ5f+6r4PHsAz7+9Qal/TK1cJuKFkUno1kqGlZbdrMwH0ATYwlWC/nBFeu2FB3NUolsTntEuy23hnQ==", 160 + "cpu": [ 161 + "arm64" 162 + ], 163 + "dev": true, 164 + "license": "Apache-2.0", 165 + "optional": true, 166 + "os": [ 167 + "darwin" 168 + ], 169 + "engines": { 170 + "node": ">=16" 171 + } 172 + }, 173 + "node_modules/@cloudflare/workerd-linux-64": { 174 + "version": "1.20250428.0", 175 + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250428.0.tgz", 176 + "integrity": "sha512-9eCbj+R3CKqpiXP6DfAA20DxKge+OTj7Hyw3ZewiEhWH9INIHiJwJQYybu4iq9kJEGjnGvxgguLFjSCWm26hgg==", 177 + "cpu": [ 178 + "x64" 179 + ], 180 + "dev": true, 181 + "license": "Apache-2.0", 182 + "optional": true, 183 + "os": [ 184 + "linux" 185 + ], 186 + "engines": { 187 + "node": ">=16" 188 + } 189 + }, 190 + "node_modules/@cloudflare/workerd-linux-arm64": { 191 + "version": "1.20250428.0", 192 + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250428.0.tgz", 193 + "integrity": "sha512-D9NRBnW46nl1EQsP13qfkYb5lbt4C6nxl38SBKY/NOcZAUoHzNB5K0GaK8LxvpkM7X/97ySojlMfR5jh5DNXYQ==", 194 + "cpu": [ 195 + "arm64" 196 + ], 197 + "dev": true, 198 + "license": "Apache-2.0", 199 + "optional": true, 200 + "os": [ 201 + "linux" 202 + ], 203 + "engines": { 204 + "node": ">=16" 205 + } 206 + }, 207 + "node_modules/@cloudflare/workerd-windows-64": { 208 + "version": "1.20250428.0", 209 + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250428.0.tgz", 210 + "integrity": "sha512-RQCRj28eitjKD0tmei6iFOuWqMuHMHdNGEigRmbkmuTlpbWHNAoHikgCzZQ/dkKDdatA76TmcpbyECNf31oaTA==", 211 + "cpu": [ 212 + "x64" 213 + ], 214 + "dev": true, 215 + "license": "Apache-2.0", 216 + "optional": true, 217 + "os": [ 218 + "win32" 219 + ], 220 + "engines": { 221 + "node": ">=16" 222 + } 223 + }, 224 + "node_modules/@cspotcode/source-map-support": { 225 + "version": "0.8.1", 226 + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", 227 + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", 228 + "dev": true, 229 + "license": "MIT", 230 + "dependencies": { 231 + "@jridgewell/trace-mapping": "0.3.9" 232 + }, 233 + "engines": { 234 + "node": ">=12" 235 + } 236 + }, 237 + "node_modules/@emnapi/runtime": { 238 + "version": "1.4.3", 239 + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", 240 + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", 241 + "dev": true, 242 + "license": "MIT", 243 + "optional": true, 244 + "dependencies": { 245 + "tslib": "^2.4.0" 246 + } 247 + }, 248 + "node_modules/@esbuild/aix-ppc64": { 249 + "version": "0.25.3", 250 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", 251 + "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", 252 + "cpu": [ 253 + "ppc64" 254 + ], 255 + "dev": true, 256 + "license": "MIT", 257 + "optional": true, 258 + "os": [ 259 + "aix" 260 + ], 261 + "engines": { 262 + "node": ">=18" 263 + } 264 + }, 265 + "node_modules/@esbuild/android-arm": { 266 + "version": "0.25.3", 267 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", 268 + "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", 269 + "cpu": [ 270 + "arm" 271 + ], 272 + "dev": true, 273 + "license": "MIT", 274 + "optional": true, 275 + "os": [ 276 + "android" 277 + ], 278 + "engines": { 279 + "node": ">=18" 280 + } 281 + }, 282 + "node_modules/@esbuild/android-arm64": { 283 + "version": "0.25.3", 284 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", 285 + "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", 286 + "cpu": [ 287 + "arm64" 288 + ], 289 + "dev": true, 290 + "license": "MIT", 291 + "optional": true, 292 + "os": [ 293 + "android" 294 + ], 295 + "engines": { 296 + "node": ">=18" 297 + } 298 + }, 299 + "node_modules/@esbuild/android-x64": { 300 + "version": "0.25.3", 301 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", 302 + "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", 303 + "cpu": [ 304 + "x64" 305 + ], 306 + "dev": true, 307 + "license": "MIT", 308 + "optional": true, 309 + "os": [ 310 + "android" 311 + ], 312 + "engines": { 313 + "node": ">=18" 314 + } 315 + }, 316 + "node_modules/@esbuild/darwin-arm64": { 317 + "version": "0.25.3", 318 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", 319 + "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", 320 + "cpu": [ 321 + "arm64" 322 + ], 323 + "dev": true, 324 + "license": "MIT", 325 + "optional": true, 326 + "os": [ 327 + "darwin" 328 + ], 329 + "engines": { 330 + "node": ">=18" 331 + } 332 + }, 333 + "node_modules/@esbuild/darwin-x64": { 334 + "version": "0.25.3", 335 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", 336 + "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", 337 + "cpu": [ 338 + "x64" 339 + ], 340 + "dev": true, 341 + "license": "MIT", 342 + "optional": true, 343 + "os": [ 344 + "darwin" 345 + ], 346 + "engines": { 347 + "node": ">=18" 348 + } 349 + }, 350 + "node_modules/@esbuild/freebsd-arm64": { 351 + "version": "0.25.3", 352 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", 353 + "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", 354 + "cpu": [ 355 + "arm64" 356 + ], 357 + "dev": true, 358 + "license": "MIT", 359 + "optional": true, 360 + "os": [ 361 + "freebsd" 362 + ], 363 + "engines": { 364 + "node": ">=18" 365 + } 366 + }, 367 + "node_modules/@esbuild/freebsd-x64": { 368 + "version": "0.25.3", 369 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", 370 + "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", 371 + "cpu": [ 372 + "x64" 373 + ], 374 + "dev": true, 375 + "license": "MIT", 376 + "optional": true, 377 + "os": [ 378 + "freebsd" 379 + ], 380 + "engines": { 381 + "node": ">=18" 382 + } 383 + }, 384 + "node_modules/@esbuild/linux-arm": { 385 + "version": "0.25.3", 386 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", 387 + "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", 388 + "cpu": [ 389 + "arm" 390 + ], 391 + "dev": true, 392 + "license": "MIT", 393 + "optional": true, 394 + "os": [ 395 + "linux" 396 + ], 397 + "engines": { 398 + "node": ">=18" 399 + } 400 + }, 401 + "node_modules/@esbuild/linux-arm64": { 402 + "version": "0.25.3", 403 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", 404 + "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", 405 + "cpu": [ 406 + "arm64" 407 + ], 408 + "dev": true, 409 + "license": "MIT", 410 + "optional": true, 411 + "os": [ 412 + "linux" 413 + ], 414 + "engines": { 415 + "node": ">=18" 416 + } 417 + }, 418 + "node_modules/@esbuild/linux-ia32": { 419 + "version": "0.25.3", 420 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", 421 + "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", 422 + "cpu": [ 423 + "ia32" 424 + ], 425 + "dev": true, 426 + "license": "MIT", 427 + "optional": true, 428 + "os": [ 429 + "linux" 430 + ], 431 + "engines": { 432 + "node": ">=18" 433 + } 434 + }, 435 + "node_modules/@esbuild/linux-loong64": { 436 + "version": "0.25.3", 437 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", 438 + "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", 439 + "cpu": [ 440 + "loong64" 441 + ], 442 + "dev": true, 443 + "license": "MIT", 444 + "optional": true, 445 + "os": [ 446 + "linux" 447 + ], 448 + "engines": { 449 + "node": ">=18" 450 + } 451 + }, 452 + "node_modules/@esbuild/linux-mips64el": { 453 + "version": "0.25.3", 454 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", 455 + "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", 456 + "cpu": [ 457 + "mips64el" 458 + ], 459 + "dev": true, 460 + "license": "MIT", 461 + "optional": true, 462 + "os": [ 463 + "linux" 464 + ], 465 + "engines": { 466 + "node": ">=18" 467 + } 468 + }, 469 + "node_modules/@esbuild/linux-ppc64": { 470 + "version": "0.25.3", 471 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", 472 + "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", 473 + "cpu": [ 474 + "ppc64" 475 + ], 476 + "dev": true, 477 + "license": "MIT", 478 + "optional": true, 479 + "os": [ 480 + "linux" 481 + ], 482 + "engines": { 483 + "node": ">=18" 484 + } 485 + }, 486 + "node_modules/@esbuild/linux-riscv64": { 487 + "version": "0.25.3", 488 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", 489 + "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", 490 + "cpu": [ 491 + "riscv64" 492 + ], 493 + "dev": true, 494 + "license": "MIT", 495 + "optional": true, 496 + "os": [ 497 + "linux" 498 + ], 499 + "engines": { 500 + "node": ">=18" 501 + } 502 + }, 503 + "node_modules/@esbuild/linux-s390x": { 504 + "version": "0.25.3", 505 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", 506 + "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", 507 + "cpu": [ 508 + "s390x" 509 + ], 510 + "dev": true, 511 + "license": "MIT", 512 + "optional": true, 513 + "os": [ 514 + "linux" 515 + ], 516 + "engines": { 517 + "node": ">=18" 518 + } 519 + }, 520 + "node_modules/@esbuild/linux-x64": { 521 + "version": "0.25.3", 522 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", 523 + "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", 524 + "cpu": [ 525 + "x64" 526 + ], 527 + "dev": true, 528 + "license": "MIT", 529 + "optional": true, 530 + "os": [ 531 + "linux" 532 + ], 533 + "engines": { 534 + "node": ">=18" 535 + } 536 + }, 537 + "node_modules/@esbuild/netbsd-arm64": { 538 + "version": "0.25.3", 539 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", 540 + "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", 541 + "cpu": [ 542 + "arm64" 543 + ], 544 + "dev": true, 545 + "license": "MIT", 546 + "optional": true, 547 + "os": [ 548 + "netbsd" 549 + ], 550 + "engines": { 551 + "node": ">=18" 552 + } 553 + }, 554 + "node_modules/@esbuild/netbsd-x64": { 555 + "version": "0.25.3", 556 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", 557 + "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", 558 + "cpu": [ 559 + "x64" 560 + ], 561 + "dev": true, 562 + "license": "MIT", 563 + "optional": true, 564 + "os": [ 565 + "netbsd" 566 + ], 567 + "engines": { 568 + "node": ">=18" 569 + } 570 + }, 571 + "node_modules/@esbuild/openbsd-arm64": { 572 + "version": "0.25.3", 573 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", 574 + "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", 575 + "cpu": [ 576 + "arm64" 577 + ], 578 + "dev": true, 579 + "license": "MIT", 580 + "optional": true, 581 + "os": [ 582 + "openbsd" 583 + ], 584 + "engines": { 585 + "node": ">=18" 586 + } 587 + }, 588 + "node_modules/@esbuild/openbsd-x64": { 589 + "version": "0.25.3", 590 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", 591 + "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", 592 + "cpu": [ 593 + "x64" 594 + ], 595 + "dev": true, 596 + "license": "MIT", 597 + "optional": true, 598 + "os": [ 599 + "openbsd" 600 + ], 601 + "engines": { 602 + "node": ">=18" 603 + } 604 + }, 605 + "node_modules/@esbuild/sunos-x64": { 606 + "version": "0.25.3", 607 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", 608 + "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", 609 + "cpu": [ 610 + "x64" 611 + ], 612 + "dev": true, 613 + "license": "MIT", 614 + "optional": true, 615 + "os": [ 616 + "sunos" 617 + ], 618 + "engines": { 619 + "node": ">=18" 620 + } 621 + }, 622 + "node_modules/@esbuild/win32-arm64": { 623 + "version": "0.25.3", 624 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", 625 + "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", 626 + "cpu": [ 627 + "arm64" 628 + ], 629 + "dev": true, 630 + "license": "MIT", 631 + "optional": true, 632 + "os": [ 633 + "win32" 634 + ], 635 + "engines": { 636 + "node": ">=18" 637 + } 638 + }, 639 + "node_modules/@esbuild/win32-ia32": { 640 + "version": "0.25.3", 641 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", 642 + "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", 643 + "cpu": [ 644 + "ia32" 645 + ], 646 + "dev": true, 647 + "license": "MIT", 648 + "optional": true, 649 + "os": [ 650 + "win32" 651 + ], 652 + "engines": { 653 + "node": ">=18" 654 + } 655 + }, 656 + "node_modules/@esbuild/win32-x64": { 657 + "version": "0.25.3", 658 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", 659 + "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", 660 + "cpu": [ 661 + "x64" 662 + ], 663 + "dev": true, 664 + "license": "MIT", 665 + "optional": true, 666 + "os": [ 667 + "win32" 668 + ], 669 + "engines": { 670 + "node": ">=18" 671 + } 672 + }, 673 + "node_modules/@fastify/busboy": { 674 + "version": "2.1.1", 675 + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", 676 + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", 677 + "dev": true, 678 + "license": "MIT", 679 + "engines": { 680 + "node": ">=14" 681 + } 682 + }, 683 + "node_modules/@img/sharp-darwin-arm64": { 684 + "version": "0.33.5", 685 + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", 686 + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", 687 + "cpu": [ 688 + "arm64" 689 + ], 690 + "dev": true, 691 + "license": "Apache-2.0", 692 + "optional": true, 693 + "os": [ 694 + "darwin" 695 + ], 696 + "engines": { 697 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 698 + }, 699 + "funding": { 700 + "url": "https://opencollective.com/libvips" 701 + }, 702 + "optionalDependencies": { 703 + "@img/sharp-libvips-darwin-arm64": "1.0.4" 704 + } 705 + }, 706 + "node_modules/@img/sharp-darwin-x64": { 707 + "version": "0.33.5", 708 + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", 709 + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", 710 + "cpu": [ 711 + "x64" 712 + ], 713 + "dev": true, 714 + "license": "Apache-2.0", 715 + "optional": true, 716 + "os": [ 717 + "darwin" 718 + ], 719 + "engines": { 720 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 721 + }, 722 + "funding": { 723 + "url": "https://opencollective.com/libvips" 724 + }, 725 + "optionalDependencies": { 726 + "@img/sharp-libvips-darwin-x64": "1.0.4" 727 + } 728 + }, 729 + "node_modules/@img/sharp-libvips-darwin-arm64": { 730 + "version": "1.0.4", 731 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", 732 + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", 733 + "cpu": [ 734 + "arm64" 735 + ], 736 + "dev": true, 737 + "license": "LGPL-3.0-or-later", 738 + "optional": true, 739 + "os": [ 740 + "darwin" 741 + ], 742 + "funding": { 743 + "url": "https://opencollective.com/libvips" 744 + } 745 + }, 746 + "node_modules/@img/sharp-libvips-darwin-x64": { 747 + "version": "1.0.4", 748 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", 749 + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", 750 + "cpu": [ 751 + "x64" 752 + ], 753 + "dev": true, 754 + "license": "LGPL-3.0-or-later", 755 + "optional": true, 756 + "os": [ 757 + "darwin" 758 + ], 759 + "funding": { 760 + "url": "https://opencollective.com/libvips" 761 + } 762 + }, 763 + "node_modules/@img/sharp-libvips-linux-arm": { 764 + "version": "1.0.5", 765 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", 766 + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", 767 + "cpu": [ 768 + "arm" 769 + ], 770 + "dev": true, 771 + "license": "LGPL-3.0-or-later", 772 + "optional": true, 773 + "os": [ 774 + "linux" 775 + ], 776 + "funding": { 777 + "url": "https://opencollective.com/libvips" 778 + } 779 + }, 780 + "node_modules/@img/sharp-libvips-linux-arm64": { 781 + "version": "1.0.4", 782 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", 783 + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", 784 + "cpu": [ 785 + "arm64" 786 + ], 787 + "dev": true, 788 + "license": "LGPL-3.0-or-later", 789 + "optional": true, 790 + "os": [ 791 + "linux" 792 + ], 793 + "funding": { 794 + "url": "https://opencollective.com/libvips" 795 + } 796 + }, 797 + "node_modules/@img/sharp-libvips-linux-s390x": { 798 + "version": "1.0.4", 799 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", 800 + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", 801 + "cpu": [ 802 + "s390x" 803 + ], 804 + "dev": true, 805 + "license": "LGPL-3.0-or-later", 806 + "optional": true, 807 + "os": [ 808 + "linux" 809 + ], 810 + "funding": { 811 + "url": "https://opencollective.com/libvips" 812 + } 813 + }, 814 + "node_modules/@img/sharp-libvips-linux-x64": { 815 + "version": "1.0.4", 816 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", 817 + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", 818 + "cpu": [ 819 + "x64" 820 + ], 821 + "dev": true, 822 + "license": "LGPL-3.0-or-later", 823 + "optional": true, 824 + "os": [ 825 + "linux" 826 + ], 827 + "funding": { 828 + "url": "https://opencollective.com/libvips" 829 + } 830 + }, 831 + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { 832 + "version": "1.0.4", 833 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", 834 + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", 835 + "cpu": [ 836 + "arm64" 837 + ], 838 + "dev": true, 839 + "license": "LGPL-3.0-or-later", 840 + "optional": true, 841 + "os": [ 842 + "linux" 843 + ], 844 + "funding": { 845 + "url": "https://opencollective.com/libvips" 846 + } 847 + }, 848 + "node_modules/@img/sharp-libvips-linuxmusl-x64": { 849 + "version": "1.0.4", 850 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", 851 + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", 852 + "cpu": [ 853 + "x64" 854 + ], 855 + "dev": true, 856 + "license": "LGPL-3.0-or-later", 857 + "optional": true, 858 + "os": [ 859 + "linux" 860 + ], 861 + "funding": { 862 + "url": "https://opencollective.com/libvips" 863 + } 864 + }, 865 + "node_modules/@img/sharp-linux-arm": { 866 + "version": "0.33.5", 867 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", 868 + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", 869 + "cpu": [ 870 + "arm" 871 + ], 872 + "dev": true, 873 + "license": "Apache-2.0", 874 + "optional": true, 875 + "os": [ 876 + "linux" 877 + ], 878 + "engines": { 879 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 880 + }, 881 + "funding": { 882 + "url": "https://opencollective.com/libvips" 883 + }, 884 + "optionalDependencies": { 885 + "@img/sharp-libvips-linux-arm": "1.0.5" 886 + } 887 + }, 888 + "node_modules/@img/sharp-linux-arm64": { 889 + "version": "0.33.5", 890 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", 891 + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", 892 + "cpu": [ 893 + "arm64" 894 + ], 895 + "dev": true, 896 + "license": "Apache-2.0", 897 + "optional": true, 898 + "os": [ 899 + "linux" 900 + ], 901 + "engines": { 902 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 903 + }, 904 + "funding": { 905 + "url": "https://opencollective.com/libvips" 906 + }, 907 + "optionalDependencies": { 908 + "@img/sharp-libvips-linux-arm64": "1.0.4" 909 + } 910 + }, 911 + "node_modules/@img/sharp-linux-s390x": { 912 + "version": "0.33.5", 913 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", 914 + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", 915 + "cpu": [ 916 + "s390x" 917 + ], 918 + "dev": true, 919 + "license": "Apache-2.0", 920 + "optional": true, 921 + "os": [ 922 + "linux" 923 + ], 924 + "engines": { 925 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 926 + }, 927 + "funding": { 928 + "url": "https://opencollective.com/libvips" 929 + }, 930 + "optionalDependencies": { 931 + "@img/sharp-libvips-linux-s390x": "1.0.4" 932 + } 933 + }, 934 + "node_modules/@img/sharp-linux-x64": { 935 + "version": "0.33.5", 936 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", 937 + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", 938 + "cpu": [ 939 + "x64" 940 + ], 941 + "dev": true, 942 + "license": "Apache-2.0", 943 + "optional": true, 944 + "os": [ 945 + "linux" 946 + ], 947 + "engines": { 948 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 949 + }, 950 + "funding": { 951 + "url": "https://opencollective.com/libvips" 952 + }, 953 + "optionalDependencies": { 954 + "@img/sharp-libvips-linux-x64": "1.0.4" 955 + } 956 + }, 957 + "node_modules/@img/sharp-linuxmusl-arm64": { 958 + "version": "0.33.5", 959 + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", 960 + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", 961 + "cpu": [ 962 + "arm64" 963 + ], 964 + "dev": true, 965 + "license": "Apache-2.0", 966 + "optional": true, 967 + "os": [ 968 + "linux" 969 + ], 970 + "engines": { 971 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 972 + }, 973 + "funding": { 974 + "url": "https://opencollective.com/libvips" 975 + }, 976 + "optionalDependencies": { 977 + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" 978 + } 979 + }, 980 + "node_modules/@img/sharp-linuxmusl-x64": { 981 + "version": "0.33.5", 982 + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", 983 + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", 984 + "cpu": [ 985 + "x64" 986 + ], 987 + "dev": true, 988 + "license": "Apache-2.0", 989 + "optional": true, 990 + "os": [ 991 + "linux" 992 + ], 993 + "engines": { 994 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 995 + }, 996 + "funding": { 997 + "url": "https://opencollective.com/libvips" 998 + }, 999 + "optionalDependencies": { 1000 + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" 1001 + } 1002 + }, 1003 + "node_modules/@img/sharp-wasm32": { 1004 + "version": "0.33.5", 1005 + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", 1006 + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", 1007 + "cpu": [ 1008 + "wasm32" 1009 + ], 1010 + "dev": true, 1011 + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", 1012 + "optional": true, 1013 + "dependencies": { 1014 + "@emnapi/runtime": "^1.2.0" 1015 + }, 1016 + "engines": { 1017 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1018 + }, 1019 + "funding": { 1020 + "url": "https://opencollective.com/libvips" 1021 + } 1022 + }, 1023 + "node_modules/@img/sharp-win32-ia32": { 1024 + "version": "0.33.5", 1025 + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", 1026 + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", 1027 + "cpu": [ 1028 + "ia32" 1029 + ], 1030 + "dev": true, 1031 + "license": "Apache-2.0 AND LGPL-3.0-or-later", 1032 + "optional": true, 1033 + "os": [ 1034 + "win32" 1035 + ], 1036 + "engines": { 1037 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1038 + }, 1039 + "funding": { 1040 + "url": "https://opencollective.com/libvips" 1041 + } 1042 + }, 1043 + "node_modules/@img/sharp-win32-x64": { 1044 + "version": "0.33.5", 1045 + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", 1046 + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", 1047 + "cpu": [ 1048 + "x64" 1049 + ], 1050 + "dev": true, 1051 + "license": "Apache-2.0 AND LGPL-3.0-or-later", 1052 + "optional": true, 1053 + "os": [ 1054 + "win32" 1055 + ], 1056 + "engines": { 1057 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1058 + }, 1059 + "funding": { 1060 + "url": "https://opencollective.com/libvips" 1061 + } 1062 + }, 1063 + "node_modules/@jridgewell/resolve-uri": { 1064 + "version": "3.1.2", 1065 + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 1066 + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 1067 + "dev": true, 1068 + "license": "MIT", 1069 + "engines": { 1070 + "node": ">=6.0.0" 1071 + } 1072 + }, 1073 + "node_modules/@jridgewell/sourcemap-codec": { 1074 + "version": "1.5.0", 1075 + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 1076 + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 1077 + "dev": true, 1078 + "license": "MIT" 1079 + }, 1080 + "node_modules/@jridgewell/trace-mapping": { 1081 + "version": "0.3.9", 1082 + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", 1083 + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", 1084 + "dev": true, 1085 + "license": "MIT", 1086 + "dependencies": { 1087 + "@jridgewell/resolve-uri": "^3.0.3", 1088 + "@jridgewell/sourcemap-codec": "^1.4.10" 1089 + } 1090 + }, 1091 + "node_modules/@rollup/rollup-android-arm-eabi": { 1092 + "version": "4.40.1", 1093 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.1.tgz", 1094 + "integrity": "sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==", 1095 + "cpu": [ 1096 + "arm" 1097 + ], 1098 + "dev": true, 1099 + "license": "MIT", 1100 + "optional": true, 1101 + "os": [ 1102 + "android" 1103 + ] 1104 + }, 1105 + "node_modules/@rollup/rollup-android-arm64": { 1106 + "version": "4.40.1", 1107 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.1.tgz", 1108 + "integrity": "sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==", 1109 + "cpu": [ 1110 + "arm64" 1111 + ], 1112 + "dev": true, 1113 + "license": "MIT", 1114 + "optional": true, 1115 + "os": [ 1116 + "android" 1117 + ] 1118 + }, 1119 + "node_modules/@rollup/rollup-darwin-arm64": { 1120 + "version": "4.40.1", 1121 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.1.tgz", 1122 + "integrity": "sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==", 1123 + "cpu": [ 1124 + "arm64" 1125 + ], 1126 + "dev": true, 1127 + "license": "MIT", 1128 + "optional": true, 1129 + "os": [ 1130 + "darwin" 1131 + ] 1132 + }, 1133 + "node_modules/@rollup/rollup-darwin-x64": { 1134 + "version": "4.40.1", 1135 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.1.tgz", 1136 + "integrity": "sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==", 1137 + "cpu": [ 1138 + "x64" 1139 + ], 1140 + "dev": true, 1141 + "license": "MIT", 1142 + "optional": true, 1143 + "os": [ 1144 + "darwin" 1145 + ] 1146 + }, 1147 + "node_modules/@rollup/rollup-freebsd-arm64": { 1148 + "version": "4.40.1", 1149 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.1.tgz", 1150 + "integrity": "sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==", 1151 + "cpu": [ 1152 + "arm64" 1153 + ], 1154 + "dev": true, 1155 + "license": "MIT", 1156 + "optional": true, 1157 + "os": [ 1158 + "freebsd" 1159 + ] 1160 + }, 1161 + "node_modules/@rollup/rollup-freebsd-x64": { 1162 + "version": "4.40.1", 1163 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.1.tgz", 1164 + "integrity": "sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==", 1165 + "cpu": [ 1166 + "x64" 1167 + ], 1168 + "dev": true, 1169 + "license": "MIT", 1170 + "optional": true, 1171 + "os": [ 1172 + "freebsd" 1173 + ] 1174 + }, 1175 + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 1176 + "version": "4.40.1", 1177 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.1.tgz", 1178 + "integrity": "sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==", 1179 + "cpu": [ 1180 + "arm" 1181 + ], 1182 + "dev": true, 1183 + "license": "MIT", 1184 + "optional": true, 1185 + "os": [ 1186 + "linux" 1187 + ] 1188 + }, 1189 + "node_modules/@rollup/rollup-linux-arm-musleabihf": { 1190 + "version": "4.40.1", 1191 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.1.tgz", 1192 + "integrity": "sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==", 1193 + "cpu": [ 1194 + "arm" 1195 + ], 1196 + "dev": true, 1197 + "license": "MIT", 1198 + "optional": true, 1199 + "os": [ 1200 + "linux" 1201 + ] 1202 + }, 1203 + "node_modules/@rollup/rollup-linux-arm64-gnu": { 1204 + "version": "4.40.1", 1205 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.1.tgz", 1206 + "integrity": "sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==", 1207 + "cpu": [ 1208 + "arm64" 1209 + ], 1210 + "dev": true, 1211 + "license": "MIT", 1212 + "optional": true, 1213 + "os": [ 1214 + "linux" 1215 + ] 1216 + }, 1217 + "node_modules/@rollup/rollup-linux-arm64-musl": { 1218 + "version": "4.40.1", 1219 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.1.tgz", 1220 + "integrity": "sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==", 1221 + "cpu": [ 1222 + "arm64" 1223 + ], 1224 + "dev": true, 1225 + "license": "MIT", 1226 + "optional": true, 1227 + "os": [ 1228 + "linux" 1229 + ] 1230 + }, 1231 + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 1232 + "version": "4.40.1", 1233 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.1.tgz", 1234 + "integrity": "sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==", 1235 + "cpu": [ 1236 + "loong64" 1237 + ], 1238 + "dev": true, 1239 + "license": "MIT", 1240 + "optional": true, 1241 + "os": [ 1242 + "linux" 1243 + ] 1244 + }, 1245 + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 1246 + "version": "4.40.1", 1247 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.1.tgz", 1248 + "integrity": "sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==", 1249 + "cpu": [ 1250 + "ppc64" 1251 + ], 1252 + "dev": true, 1253 + "license": "MIT", 1254 + "optional": true, 1255 + "os": [ 1256 + "linux" 1257 + ] 1258 + }, 1259 + "node_modules/@rollup/rollup-linux-riscv64-gnu": { 1260 + "version": "4.40.1", 1261 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.1.tgz", 1262 + "integrity": "sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==", 1263 + "cpu": [ 1264 + "riscv64" 1265 + ], 1266 + "dev": true, 1267 + "license": "MIT", 1268 + "optional": true, 1269 + "os": [ 1270 + "linux" 1271 + ] 1272 + }, 1273 + "node_modules/@rollup/rollup-linux-riscv64-musl": { 1274 + "version": "4.40.1", 1275 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.1.tgz", 1276 + "integrity": "sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==", 1277 + "cpu": [ 1278 + "riscv64" 1279 + ], 1280 + "dev": true, 1281 + "license": "MIT", 1282 + "optional": true, 1283 + "os": [ 1284 + "linux" 1285 + ] 1286 + }, 1287 + "node_modules/@rollup/rollup-linux-s390x-gnu": { 1288 + "version": "4.40.1", 1289 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.1.tgz", 1290 + "integrity": "sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==", 1291 + "cpu": [ 1292 + "s390x" 1293 + ], 1294 + "dev": true, 1295 + "license": "MIT", 1296 + "optional": true, 1297 + "os": [ 1298 + "linux" 1299 + ] 1300 + }, 1301 + "node_modules/@rollup/rollup-linux-x64-gnu": { 1302 + "version": "4.40.1", 1303 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.1.tgz", 1304 + "integrity": "sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==", 1305 + "cpu": [ 1306 + "x64" 1307 + ], 1308 + "dev": true, 1309 + "license": "MIT", 1310 + "optional": true, 1311 + "os": [ 1312 + "linux" 1313 + ] 1314 + }, 1315 + "node_modules/@rollup/rollup-linux-x64-musl": { 1316 + "version": "4.40.1", 1317 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.1.tgz", 1318 + "integrity": "sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==", 1319 + "cpu": [ 1320 + "x64" 1321 + ], 1322 + "dev": true, 1323 + "license": "MIT", 1324 + "optional": true, 1325 + "os": [ 1326 + "linux" 1327 + ] 1328 + }, 1329 + "node_modules/@rollup/rollup-win32-arm64-msvc": { 1330 + "version": "4.40.1", 1331 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.1.tgz", 1332 + "integrity": "sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==", 1333 + "cpu": [ 1334 + "arm64" 1335 + ], 1336 + "dev": true, 1337 + "license": "MIT", 1338 + "optional": true, 1339 + "os": [ 1340 + "win32" 1341 + ] 1342 + }, 1343 + "node_modules/@rollup/rollup-win32-ia32-msvc": { 1344 + "version": "4.40.1", 1345 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.1.tgz", 1346 + "integrity": "sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==", 1347 + "cpu": [ 1348 + "ia32" 1349 + ], 1350 + "dev": true, 1351 + "license": "MIT", 1352 + "optional": true, 1353 + "os": [ 1354 + "win32" 1355 + ] 1356 + }, 1357 + "node_modules/@rollup/rollup-win32-x64-msvc": { 1358 + "version": "4.40.1", 1359 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.1.tgz", 1360 + "integrity": "sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==", 1361 + "cpu": [ 1362 + "x64" 1363 + ], 1364 + "dev": true, 1365 + "license": "MIT", 1366 + "optional": true, 1367 + "os": [ 1368 + "win32" 1369 + ] 1370 + }, 1371 + "node_modules/@standard-schema/spec": { 1372 + "version": "1.1.0", 1373 + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", 1374 + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", 1375 + "license": "MIT" 1376 + }, 1377 + "node_modules/@types/estree": { 1378 + "version": "1.0.7", 1379 + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", 1380 + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", 1381 + "dev": true, 1382 + "license": "MIT" 1383 + }, 1384 + "node_modules/@vitest/expect": { 1385 + "version": "3.0.9", 1386 + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", 1387 + "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", 1388 + "dev": true, 1389 + "license": "MIT", 1390 + "dependencies": { 1391 + "@vitest/spy": "3.0.9", 1392 + "@vitest/utils": "3.0.9", 1393 + "chai": "^5.2.0", 1394 + "tinyrainbow": "^2.0.0" 1395 + }, 1396 + "funding": { 1397 + "url": "https://opencollective.com/vitest" 1398 + } 1399 + }, 1400 + "node_modules/@vitest/mocker": { 1401 + "version": "3.0.9", 1402 + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", 1403 + "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", 1404 + "dev": true, 1405 + "license": "MIT", 1406 + "dependencies": { 1407 + "@vitest/spy": "3.0.9", 1408 + "estree-walker": "^3.0.3", 1409 + "magic-string": "^0.30.17" 1410 + }, 1411 + "funding": { 1412 + "url": "https://opencollective.com/vitest" 1413 + }, 1414 + "peerDependencies": { 1415 + "msw": "^2.4.9", 1416 + "vite": "^5.0.0 || ^6.0.0" 1417 + }, 1418 + "peerDependenciesMeta": { 1419 + "msw": { 1420 + "optional": true 1421 + }, 1422 + "vite": { 1423 + "optional": true 1424 + } 1425 + } 1426 + }, 1427 + "node_modules/@vitest/pretty-format": { 1428 + "version": "3.1.2", 1429 + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", 1430 + "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", 1431 + "dev": true, 1432 + "license": "MIT", 1433 + "dependencies": { 1434 + "tinyrainbow": "^2.0.0" 1435 + }, 1436 + "funding": { 1437 + "url": "https://opencollective.com/vitest" 1438 + } 1439 + }, 1440 + "node_modules/@vitest/runner": { 1441 + "version": "3.0.9", 1442 + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", 1443 + "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", 1444 + "dev": true, 1445 + "license": "MIT", 1446 + "dependencies": { 1447 + "@vitest/utils": "3.0.9", 1448 + "pathe": "^2.0.3" 1449 + }, 1450 + "funding": { 1451 + "url": "https://opencollective.com/vitest" 1452 + } 1453 + }, 1454 + "node_modules/@vitest/snapshot": { 1455 + "version": "3.0.9", 1456 + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", 1457 + "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", 1458 + "dev": true, 1459 + "license": "MIT", 1460 + "dependencies": { 1461 + "@vitest/pretty-format": "3.0.9", 1462 + "magic-string": "^0.30.17", 1463 + "pathe": "^2.0.3" 1464 + }, 1465 + "funding": { 1466 + "url": "https://opencollective.com/vitest" 1467 + } 1468 + }, 1469 + "node_modules/@vitest/snapshot/node_modules/@vitest/pretty-format": { 1470 + "version": "3.0.9", 1471 + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", 1472 + "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", 1473 + "dev": true, 1474 + "license": "MIT", 1475 + "dependencies": { 1476 + "tinyrainbow": "^2.0.0" 1477 + }, 1478 + "funding": { 1479 + "url": "https://opencollective.com/vitest" 1480 + } 1481 + }, 1482 + "node_modules/@vitest/spy": { 1483 + "version": "3.0.9", 1484 + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", 1485 + "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", 1486 + "dev": true, 1487 + "license": "MIT", 1488 + "dependencies": { 1489 + "tinyspy": "^3.0.2" 1490 + }, 1491 + "funding": { 1492 + "url": "https://opencollective.com/vitest" 1493 + } 1494 + }, 1495 + "node_modules/@vitest/utils": { 1496 + "version": "3.0.9", 1497 + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", 1498 + "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", 1499 + "dev": true, 1500 + "license": "MIT", 1501 + "dependencies": { 1502 + "@vitest/pretty-format": "3.0.9", 1503 + "loupe": "^3.1.3", 1504 + "tinyrainbow": "^2.0.0" 1505 + }, 1506 + "funding": { 1507 + "url": "https://opencollective.com/vitest" 1508 + } 1509 + }, 1510 + "node_modules/@vitest/utils/node_modules/@vitest/pretty-format": { 1511 + "version": "3.0.9", 1512 + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", 1513 + "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", 1514 + "dev": true, 1515 + "license": "MIT", 1516 + "dependencies": { 1517 + "tinyrainbow": "^2.0.0" 1518 + }, 1519 + "funding": { 1520 + "url": "https://opencollective.com/vitest" 1521 + } 1522 + }, 1523 + "node_modules/acorn": { 1524 + "version": "8.14.0", 1525 + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", 1526 + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", 1527 + "dev": true, 1528 + "license": "MIT", 1529 + "bin": { 1530 + "acorn": "bin/acorn" 1531 + }, 1532 + "engines": { 1533 + "node": ">=0.4.0" 1534 + } 1535 + }, 1536 + "node_modules/acorn-walk": { 1537 + "version": "8.3.2", 1538 + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", 1539 + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", 1540 + "dev": true, 1541 + "license": "MIT", 1542 + "engines": { 1543 + "node": ">=0.4.0" 1544 + } 1545 + }, 1546 + "node_modules/as-table": { 1547 + "version": "1.0.55", 1548 + "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", 1549 + "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", 1550 + "dev": true, 1551 + "license": "MIT", 1552 + "dependencies": { 1553 + "printable-characters": "^1.0.42" 1554 + } 1555 + }, 1556 + "node_modules/assertion-error": { 1557 + "version": "2.0.1", 1558 + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", 1559 + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", 1560 + "dev": true, 1561 + "license": "MIT", 1562 + "engines": { 1563 + "node": ">=12" 1564 + } 1565 + }, 1566 + "node_modules/birpc": { 1567 + "version": "0.2.14", 1568 + "resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.14.tgz", 1569 + "integrity": "sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA==", 1570 + "dev": true, 1571 + "license": "MIT", 1572 + "funding": { 1573 + "url": "https://github.com/sponsors/antfu" 1574 + } 1575 + }, 1576 + "node_modules/blake3-wasm": { 1577 + "version": "2.1.5", 1578 + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", 1579 + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", 1580 + "dev": true, 1581 + "license": "MIT" 1582 + }, 1583 + "node_modules/cac": { 1584 + "version": "6.7.14", 1585 + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 1586 + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 1587 + "dev": true, 1588 + "license": "MIT", 1589 + "engines": { 1590 + "node": ">=8" 1591 + } 1592 + }, 1593 + "node_modules/chai": { 1594 + "version": "5.2.0", 1595 + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", 1596 + "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", 1597 + "dev": true, 1598 + "license": "MIT", 1599 + "dependencies": { 1600 + "assertion-error": "^2.0.1", 1601 + "check-error": "^2.1.1", 1602 + "deep-eql": "^5.0.1", 1603 + "loupe": "^3.1.0", 1604 + "pathval": "^2.0.0" 1605 + }, 1606 + "engines": { 1607 + "node": ">=12" 1608 + } 1609 + }, 1610 + "node_modules/check-error": { 1611 + "version": "2.1.1", 1612 + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", 1613 + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", 1614 + "dev": true, 1615 + "license": "MIT", 1616 + "engines": { 1617 + "node": ">= 16" 1618 + } 1619 + }, 1620 + "node_modules/cjs-module-lexer": { 1621 + "version": "1.4.3", 1622 + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", 1623 + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", 1624 + "dev": true, 1625 + "license": "MIT" 1626 + }, 1627 + "node_modules/color": { 1628 + "version": "4.2.3", 1629 + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", 1630 + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", 1631 + "dev": true, 1632 + "license": "MIT", 1633 + "optional": true, 1634 + "dependencies": { 1635 + "color-convert": "^2.0.1", 1636 + "color-string": "^1.9.0" 1637 + }, 1638 + "engines": { 1639 + "node": ">=12.5.0" 1640 + } 1641 + }, 1642 + "node_modules/color-convert": { 1643 + "version": "2.0.1", 1644 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1645 + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1646 + "dev": true, 1647 + "license": "MIT", 1648 + "optional": true, 1649 + "dependencies": { 1650 + "color-name": "~1.1.4" 1651 + }, 1652 + "engines": { 1653 + "node": ">=7.0.0" 1654 + } 1655 + }, 1656 + "node_modules/color-name": { 1657 + "version": "1.1.4", 1658 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1659 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1660 + "dev": true, 1661 + "license": "MIT", 1662 + "optional": true 1663 + }, 1664 + "node_modules/color-string": { 1665 + "version": "1.9.1", 1666 + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", 1667 + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", 1668 + "dev": true, 1669 + "license": "MIT", 1670 + "optional": true, 1671 + "dependencies": { 1672 + "color-name": "^1.0.0", 1673 + "simple-swizzle": "^0.2.2" 1674 + } 1675 + }, 1676 + "node_modules/cookie": { 1677 + "version": "0.7.2", 1678 + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 1679 + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 1680 + "dev": true, 1681 + "license": "MIT", 1682 + "engines": { 1683 + "node": ">= 0.6" 1684 + } 1685 + }, 1686 + "node_modules/data-uri-to-buffer": { 1687 + "version": "2.0.2", 1688 + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", 1689 + "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", 1690 + "dev": true, 1691 + "license": "MIT" 1692 + }, 1693 + "node_modules/debug": { 1694 + "version": "4.4.0", 1695 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 1696 + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 1697 + "dev": true, 1698 + "license": "MIT", 1699 + "dependencies": { 1700 + "ms": "^2.1.3" 1701 + }, 1702 + "engines": { 1703 + "node": ">=6.0" 1704 + }, 1705 + "peerDependenciesMeta": { 1706 + "supports-color": { 1707 + "optional": true 1708 + } 1709 + } 1710 + }, 1711 + "node_modules/deep-eql": { 1712 + "version": "5.0.2", 1713 + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", 1714 + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", 1715 + "dev": true, 1716 + "license": "MIT", 1717 + "engines": { 1718 + "node": ">=6" 1719 + } 1720 + }, 1721 + "node_modules/defu": { 1722 + "version": "6.1.4", 1723 + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", 1724 + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", 1725 + "dev": true, 1726 + "license": "MIT" 1727 + }, 1728 + "node_modules/detect-libc": { 1729 + "version": "2.0.4", 1730 + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", 1731 + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", 1732 + "dev": true, 1733 + "license": "Apache-2.0", 1734 + "optional": true, 1735 + "engines": { 1736 + "node": ">=8" 1737 + } 1738 + }, 1739 + "node_modules/devalue": { 1740 + "version": "4.3.3", 1741 + "resolved": "https://registry.npmjs.org/devalue/-/devalue-4.3.3.tgz", 1742 + "integrity": "sha512-UH8EL6H2ifcY8TbD2QsxwCC/pr5xSwPvv85LrLXVihmHVC3T3YqTCIwnR5ak0yO1KYqlxrPVOA/JVZJYPy2ATg==", 1743 + "dev": true, 1744 + "license": "MIT" 1745 + }, 1746 + "node_modules/es-module-lexer": { 1747 + "version": "1.7.0", 1748 + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", 1749 + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", 1750 + "dev": true, 1751 + "license": "MIT" 1752 + }, 1753 + "node_modules/esbuild": { 1754 + "version": "0.25.3", 1755 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", 1756 + "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", 1757 + "dev": true, 1758 + "hasInstallScript": true, 1759 + "license": "MIT", 1760 + "bin": { 1761 + "esbuild": "bin/esbuild" 1762 + }, 1763 + "engines": { 1764 + "node": ">=18" 1765 + }, 1766 + "optionalDependencies": { 1767 + "@esbuild/aix-ppc64": "0.25.3", 1768 + "@esbuild/android-arm": "0.25.3", 1769 + "@esbuild/android-arm64": "0.25.3", 1770 + "@esbuild/android-x64": "0.25.3", 1771 + "@esbuild/darwin-arm64": "0.25.3", 1772 + "@esbuild/darwin-x64": "0.25.3", 1773 + "@esbuild/freebsd-arm64": "0.25.3", 1774 + "@esbuild/freebsd-x64": "0.25.3", 1775 + "@esbuild/linux-arm": "0.25.3", 1776 + "@esbuild/linux-arm64": "0.25.3", 1777 + "@esbuild/linux-ia32": "0.25.3", 1778 + "@esbuild/linux-loong64": "0.25.3", 1779 + "@esbuild/linux-mips64el": "0.25.3", 1780 + "@esbuild/linux-ppc64": "0.25.3", 1781 + "@esbuild/linux-riscv64": "0.25.3", 1782 + "@esbuild/linux-s390x": "0.25.3", 1783 + "@esbuild/linux-x64": "0.25.3", 1784 + "@esbuild/netbsd-arm64": "0.25.3", 1785 + "@esbuild/netbsd-x64": "0.25.3", 1786 + "@esbuild/openbsd-arm64": "0.25.3", 1787 + "@esbuild/openbsd-x64": "0.25.3", 1788 + "@esbuild/sunos-x64": "0.25.3", 1789 + "@esbuild/win32-arm64": "0.25.3", 1790 + "@esbuild/win32-ia32": "0.25.3", 1791 + "@esbuild/win32-x64": "0.25.3" 1792 + } 1793 + }, 1794 + "node_modules/esm-env": { 1795 + "version": "1.2.2", 1796 + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", 1797 + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", 1798 + "license": "MIT" 1799 + }, 1800 + "node_modules/estree-walker": { 1801 + "version": "3.0.3", 1802 + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", 1803 + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", 1804 + "dev": true, 1805 + "license": "MIT", 1806 + "dependencies": { 1807 + "@types/estree": "^1.0.0" 1808 + } 1809 + }, 1810 + "node_modules/exit-hook": { 1811 + "version": "2.2.1", 1812 + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", 1813 + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", 1814 + "dev": true, 1815 + "license": "MIT", 1816 + "engines": { 1817 + "node": ">=6" 1818 + }, 1819 + "funding": { 1820 + "url": "https://github.com/sponsors/sindresorhus" 1821 + } 1822 + }, 1823 + "node_modules/expect-type": { 1824 + "version": "1.2.1", 1825 + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", 1826 + "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", 1827 + "dev": true, 1828 + "license": "Apache-2.0", 1829 + "engines": { 1830 + "node": ">=12.0.0" 1831 + } 1832 + }, 1833 + "node_modules/exsolve": { 1834 + "version": "1.0.5", 1835 + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", 1836 + "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", 1837 + "dev": true, 1838 + "license": "MIT" 1839 + }, 1840 + "node_modules/fdir": { 1841 + "version": "6.4.4", 1842 + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", 1843 + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", 1844 + "dev": true, 1845 + "license": "MIT", 1846 + "peerDependencies": { 1847 + "picomatch": "^3 || ^4" 1848 + }, 1849 + "peerDependenciesMeta": { 1850 + "picomatch": { 1851 + "optional": true 1852 + } 1853 + } 1854 + }, 1855 + "node_modules/fsevents": { 1856 + "version": "2.3.3", 1857 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1858 + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1859 + "dev": true, 1860 + "hasInstallScript": true, 1861 + "license": "MIT", 1862 + "optional": true, 1863 + "os": [ 1864 + "darwin" 1865 + ], 1866 + "engines": { 1867 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1868 + } 1869 + }, 1870 + "node_modules/get-source": { 1871 + "version": "2.0.12", 1872 + "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", 1873 + "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", 1874 + "dev": true, 1875 + "license": "Unlicense", 1876 + "dependencies": { 1877 + "data-uri-to-buffer": "^2.0.0", 1878 + "source-map": "^0.6.1" 1879 + } 1880 + }, 1881 + "node_modules/glob-to-regexp": { 1882 + "version": "0.4.1", 1883 + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", 1884 + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", 1885 + "dev": true, 1886 + "license": "BSD-2-Clause" 1887 + }, 1888 + "node_modules/is-arrayish": { 1889 + "version": "0.3.2", 1890 + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", 1891 + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", 1892 + "dev": true, 1893 + "license": "MIT", 1894 + "optional": true 1895 + }, 1896 + "node_modules/loupe": { 1897 + "version": "3.1.3", 1898 + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", 1899 + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", 1900 + "dev": true, 1901 + "license": "MIT" 1902 + }, 1903 + "node_modules/magic-string": { 1904 + "version": "0.30.17", 1905 + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 1906 + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 1907 + "dev": true, 1908 + "license": "MIT", 1909 + "dependencies": { 1910 + "@jridgewell/sourcemap-codec": "^1.5.0" 1911 + } 1912 + }, 1913 + "node_modules/mime": { 1914 + "version": "3.0.0", 1915 + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", 1916 + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", 1917 + "dev": true, 1918 + "license": "MIT", 1919 + "bin": { 1920 + "mime": "cli.js" 1921 + }, 1922 + "engines": { 1923 + "node": ">=10.0.0" 1924 + } 1925 + }, 1926 + "node_modules/miniflare": { 1927 + "version": "4.20250428.1", 1928 + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20250428.1.tgz", 1929 + "integrity": "sha512-M3qcJXjeAEimHrEeWXEhrJiC3YHB5M3QSqqK67pOTI+lHn0QyVG/2iFUjVJ/nv+i10uxeAEva8GRGeu+tKRCmQ==", 1930 + "dev": true, 1931 + "license": "MIT", 1932 + "dependencies": { 1933 + "@cspotcode/source-map-support": "0.8.1", 1934 + "acorn": "8.14.0", 1935 + "acorn-walk": "8.3.2", 1936 + "exit-hook": "2.2.1", 1937 + "glob-to-regexp": "0.4.1", 1938 + "stoppable": "1.1.0", 1939 + "undici": "^5.28.5", 1940 + "workerd": "1.20250428.0", 1941 + "ws": "8.18.0", 1942 + "youch": "3.3.4", 1943 + "zod": "3.22.3" 1944 + }, 1945 + "bin": { 1946 + "miniflare": "bootstrap.js" 1947 + }, 1948 + "engines": { 1949 + "node": ">=18.0.0" 1950 + } 1951 + }, 1952 + "node_modules/miniflare/node_modules/zod": { 1953 + "version": "3.22.3", 1954 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", 1955 + "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", 1956 + "dev": true, 1957 + "license": "MIT", 1958 + "funding": { 1959 + "url": "https://github.com/sponsors/colinhacks" 1960 + } 1961 + }, 1962 + "node_modules/ms": { 1963 + "version": "2.1.3", 1964 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1965 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1966 + "dev": true, 1967 + "license": "MIT" 1968 + }, 1969 + "node_modules/mustache": { 1970 + "version": "4.2.0", 1971 + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", 1972 + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", 1973 + "dev": true, 1974 + "license": "MIT", 1975 + "bin": { 1976 + "mustache": "bin/mustache" 1977 + } 1978 + }, 1979 + "node_modules/nanoid": { 1980 + "version": "3.3.11", 1981 + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 1982 + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 1983 + "dev": true, 1984 + "funding": [ 1985 + { 1986 + "type": "github", 1987 + "url": "https://github.com/sponsors/ai" 1988 + } 1989 + ], 1990 + "license": "MIT", 1991 + "bin": { 1992 + "nanoid": "bin/nanoid.cjs" 1993 + }, 1994 + "engines": { 1995 + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1996 + } 1997 + }, 1998 + "node_modules/ohash": { 1999 + "version": "2.0.11", 2000 + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", 2001 + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", 2002 + "dev": true, 2003 + "license": "MIT" 2004 + }, 2005 + "node_modules/path-to-regexp": { 2006 + "version": "6.3.0", 2007 + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", 2008 + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", 2009 + "dev": true, 2010 + "license": "MIT" 2011 + }, 2012 + "node_modules/pathe": { 2013 + "version": "2.0.3", 2014 + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", 2015 + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", 2016 + "dev": true, 2017 + "license": "MIT" 2018 + }, 2019 + "node_modules/pathval": { 2020 + "version": "2.0.0", 2021 + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", 2022 + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", 2023 + "dev": true, 2024 + "license": "MIT", 2025 + "engines": { 2026 + "node": ">= 14.16" 2027 + } 2028 + }, 2029 + "node_modules/picocolors": { 2030 + "version": "1.1.1", 2031 + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 2032 + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 2033 + "dev": true, 2034 + "license": "ISC" 2035 + }, 2036 + "node_modules/picomatch": { 2037 + "version": "4.0.2", 2038 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", 2039 + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", 2040 + "dev": true, 2041 + "license": "MIT", 2042 + "engines": { 2043 + "node": ">=12" 2044 + }, 2045 + "funding": { 2046 + "url": "https://github.com/sponsors/jonschlinkert" 2047 + } 2048 + }, 2049 + "node_modules/postcss": { 2050 + "version": "8.5.3", 2051 + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", 2052 + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", 2053 + "dev": true, 2054 + "funding": [ 2055 + { 2056 + "type": "opencollective", 2057 + "url": "https://opencollective.com/postcss/" 2058 + }, 2059 + { 2060 + "type": "tidelift", 2061 + "url": "https://tidelift.com/funding/github/npm/postcss" 2062 + }, 2063 + { 2064 + "type": "github", 2065 + "url": "https://github.com/sponsors/ai" 2066 + } 2067 + ], 2068 + "license": "MIT", 2069 + "dependencies": { 2070 + "nanoid": "^3.3.8", 2071 + "picocolors": "^1.1.1", 2072 + "source-map-js": "^1.2.1" 2073 + }, 2074 + "engines": { 2075 + "node": "^10 || ^12 || >=14" 2076 + } 2077 + }, 2078 + "node_modules/printable-characters": { 2079 + "version": "1.0.42", 2080 + "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", 2081 + "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", 2082 + "dev": true, 2083 + "license": "Unlicense" 2084 + }, 2085 + "node_modules/rollup": { 2086 + "version": "4.40.1", 2087 + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.1.tgz", 2088 + "integrity": "sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==", 2089 + "dev": true, 2090 + "license": "MIT", 2091 + "dependencies": { 2092 + "@types/estree": "1.0.7" 2093 + }, 2094 + "bin": { 2095 + "rollup": "dist/bin/rollup" 2096 + }, 2097 + "engines": { 2098 + "node": ">=18.0.0", 2099 + "npm": ">=8.0.0" 2100 + }, 2101 + "optionalDependencies": { 2102 + "@rollup/rollup-android-arm-eabi": "4.40.1", 2103 + "@rollup/rollup-android-arm64": "4.40.1", 2104 + "@rollup/rollup-darwin-arm64": "4.40.1", 2105 + "@rollup/rollup-darwin-x64": "4.40.1", 2106 + "@rollup/rollup-freebsd-arm64": "4.40.1", 2107 + "@rollup/rollup-freebsd-x64": "4.40.1", 2108 + "@rollup/rollup-linux-arm-gnueabihf": "4.40.1", 2109 + "@rollup/rollup-linux-arm-musleabihf": "4.40.1", 2110 + "@rollup/rollup-linux-arm64-gnu": "4.40.1", 2111 + "@rollup/rollup-linux-arm64-musl": "4.40.1", 2112 + "@rollup/rollup-linux-loongarch64-gnu": "4.40.1", 2113 + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.1", 2114 + "@rollup/rollup-linux-riscv64-gnu": "4.40.1", 2115 + "@rollup/rollup-linux-riscv64-musl": "4.40.1", 2116 + "@rollup/rollup-linux-s390x-gnu": "4.40.1", 2117 + "@rollup/rollup-linux-x64-gnu": "4.40.1", 2118 + "@rollup/rollup-linux-x64-musl": "4.40.1", 2119 + "@rollup/rollup-win32-arm64-msvc": "4.40.1", 2120 + "@rollup/rollup-win32-ia32-msvc": "4.40.1", 2121 + "@rollup/rollup-win32-x64-msvc": "4.40.1", 2122 + "fsevents": "~2.3.2" 2123 + } 2124 + }, 2125 + "node_modules/semver": { 2126 + "version": "7.7.1", 2127 + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", 2128 + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", 2129 + "dev": true, 2130 + "license": "ISC", 2131 + "bin": { 2132 + "semver": "bin/semver.js" 2133 + }, 2134 + "engines": { 2135 + "node": ">=10" 2136 + } 2137 + }, 2138 + "node_modules/sharp": { 2139 + "version": "0.33.5", 2140 + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", 2141 + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", 2142 + "dev": true, 2143 + "hasInstallScript": true, 2144 + "license": "Apache-2.0", 2145 + "optional": true, 2146 + "dependencies": { 2147 + "color": "^4.2.3", 2148 + "detect-libc": "^2.0.3", 2149 + "semver": "^7.6.3" 2150 + }, 2151 + "engines": { 2152 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 2153 + }, 2154 + "funding": { 2155 + "url": "https://opencollective.com/libvips" 2156 + }, 2157 + "optionalDependencies": { 2158 + "@img/sharp-darwin-arm64": "0.33.5", 2159 + "@img/sharp-darwin-x64": "0.33.5", 2160 + "@img/sharp-libvips-darwin-arm64": "1.0.4", 2161 + "@img/sharp-libvips-darwin-x64": "1.0.4", 2162 + "@img/sharp-libvips-linux-arm": "1.0.5", 2163 + "@img/sharp-libvips-linux-arm64": "1.0.4", 2164 + "@img/sharp-libvips-linux-s390x": "1.0.4", 2165 + "@img/sharp-libvips-linux-x64": "1.0.4", 2166 + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", 2167 + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", 2168 + "@img/sharp-linux-arm": "0.33.5", 2169 + "@img/sharp-linux-arm64": "0.33.5", 2170 + "@img/sharp-linux-s390x": "0.33.5", 2171 + "@img/sharp-linux-x64": "0.33.5", 2172 + "@img/sharp-linuxmusl-arm64": "0.33.5", 2173 + "@img/sharp-linuxmusl-x64": "0.33.5", 2174 + "@img/sharp-wasm32": "0.33.5", 2175 + "@img/sharp-win32-ia32": "0.33.5", 2176 + "@img/sharp-win32-x64": "0.33.5" 2177 + } 2178 + }, 2179 + "node_modules/siginfo": { 2180 + "version": "2.0.0", 2181 + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", 2182 + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", 2183 + "dev": true, 2184 + "license": "ISC" 2185 + }, 2186 + "node_modules/simple-swizzle": { 2187 + "version": "0.2.2", 2188 + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", 2189 + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", 2190 + "dev": true, 2191 + "license": "MIT", 2192 + "optional": true, 2193 + "dependencies": { 2194 + "is-arrayish": "^0.3.1" 2195 + } 2196 + }, 2197 + "node_modules/source-map": { 2198 + "version": "0.6.1", 2199 + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2200 + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2201 + "dev": true, 2202 + "license": "BSD-3-Clause", 2203 + "engines": { 2204 + "node": ">=0.10.0" 2205 + } 2206 + }, 2207 + "node_modules/source-map-js": { 2208 + "version": "1.2.1", 2209 + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 2210 + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 2211 + "dev": true, 2212 + "license": "BSD-3-Clause", 2213 + "engines": { 2214 + "node": ">=0.10.0" 2215 + } 2216 + }, 2217 + "node_modules/stackback": { 2218 + "version": "0.0.2", 2219 + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", 2220 + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", 2221 + "dev": true, 2222 + "license": "MIT" 2223 + }, 2224 + "node_modules/stacktracey": { 2225 + "version": "2.1.8", 2226 + "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", 2227 + "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", 2228 + "dev": true, 2229 + "license": "Unlicense", 2230 + "dependencies": { 2231 + "as-table": "^1.0.36", 2232 + "get-source": "^2.0.12" 2233 + } 2234 + }, 2235 + "node_modules/std-env": { 2236 + "version": "3.9.0", 2237 + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", 2238 + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", 2239 + "dev": true, 2240 + "license": "MIT" 2241 + }, 2242 + "node_modules/stoppable": { 2243 + "version": "1.1.0", 2244 + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", 2245 + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", 2246 + "dev": true, 2247 + "license": "MIT", 2248 + "engines": { 2249 + "node": ">=4", 2250 + "npm": ">=6" 2251 + } 2252 + }, 2253 + "node_modules/tinybench": { 2254 + "version": "2.9.0", 2255 + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", 2256 + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", 2257 + "dev": true, 2258 + "license": "MIT" 2259 + }, 2260 + "node_modules/tinyexec": { 2261 + "version": "0.3.2", 2262 + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", 2263 + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", 2264 + "dev": true, 2265 + "license": "MIT" 2266 + }, 2267 + "node_modules/tinyglobby": { 2268 + "version": "0.2.13", 2269 + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", 2270 + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", 2271 + "dev": true, 2272 + "license": "MIT", 2273 + "dependencies": { 2274 + "fdir": "^6.4.4", 2275 + "picomatch": "^4.0.2" 2276 + }, 2277 + "engines": { 2278 + "node": ">=12.0.0" 2279 + }, 2280 + "funding": { 2281 + "url": "https://github.com/sponsors/SuperchupuDev" 2282 + } 2283 + }, 2284 + "node_modules/tinypool": { 2285 + "version": "1.0.2", 2286 + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", 2287 + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", 2288 + "dev": true, 2289 + "license": "MIT", 2290 + "engines": { 2291 + "node": "^18.0.0 || >=20.0.0" 2292 + } 2293 + }, 2294 + "node_modules/tinyrainbow": { 2295 + "version": "2.0.0", 2296 + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", 2297 + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", 2298 + "dev": true, 2299 + "license": "MIT", 2300 + "engines": { 2301 + "node": ">=14.0.0" 2302 + } 2303 + }, 2304 + "node_modules/tinyspy": { 2305 + "version": "3.0.2", 2306 + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", 2307 + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", 2308 + "dev": true, 2309 + "license": "MIT", 2310 + "engines": { 2311 + "node": ">=14.0.0" 2312 + } 2313 + }, 2314 + "node_modules/tslib": { 2315 + "version": "2.8.1", 2316 + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 2317 + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 2318 + "dev": true, 2319 + "license": "0BSD", 2320 + "optional": true 2321 + }, 2322 + "node_modules/ufo": { 2323 + "version": "1.6.1", 2324 + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", 2325 + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", 2326 + "dev": true, 2327 + "license": "MIT" 2328 + }, 2329 + "node_modules/undici": { 2330 + "version": "5.29.0", 2331 + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", 2332 + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", 2333 + "dev": true, 2334 + "license": "MIT", 2335 + "dependencies": { 2336 + "@fastify/busboy": "^2.0.0" 2337 + }, 2338 + "engines": { 2339 + "node": ">=14.0" 2340 + } 2341 + }, 2342 + "node_modules/unenv": { 2343 + "version": "2.0.0-rc.15", 2344 + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.15.tgz", 2345 + "integrity": "sha512-J/rEIZU8w6FOfLNz/hNKsnY+fFHWnu9MH4yRbSZF3xbbGHovcetXPs7sD+9p8L6CeNC//I9bhRYAOsBt2u7/OA==", 2346 + "dev": true, 2347 + "license": "MIT", 2348 + "dependencies": { 2349 + "defu": "^6.1.4", 2350 + "exsolve": "^1.0.4", 2351 + "ohash": "^2.0.11", 2352 + "pathe": "^2.0.3", 2353 + "ufo": "^1.5.4" 2354 + } 2355 + }, 2356 + "node_modules/unicode-segmenter": { 2357 + "version": "0.14.4", 2358 + "resolved": "https://registry.npmjs.org/unicode-segmenter/-/unicode-segmenter-0.14.4.tgz", 2359 + "integrity": "sha512-pR5VCiCrLrKOL6FRW61jnk9+wyMtKKowq+jyFY9oc6uHbWKhDL4yVRiI4YZPksGMK72Pahh8m0cn/0JvbDDyJg==", 2360 + "license": "MIT" 2361 + }, 2362 + "node_modules/vite": { 2363 + "version": "6.3.4", 2364 + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.4.tgz", 2365 + "integrity": "sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==", 2366 + "dev": true, 2367 + "license": "MIT", 2368 + "dependencies": { 2369 + "esbuild": "^0.25.0", 2370 + "fdir": "^6.4.4", 2371 + "picomatch": "^4.0.2", 2372 + "postcss": "^8.5.3", 2373 + "rollup": "^4.34.9", 2374 + "tinyglobby": "^0.2.13" 2375 + }, 2376 + "bin": { 2377 + "vite": "bin/vite.js" 2378 + }, 2379 + "engines": { 2380 + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2381 + }, 2382 + "funding": { 2383 + "url": "https://github.com/vitejs/vite?sponsor=1" 2384 + }, 2385 + "optionalDependencies": { 2386 + "fsevents": "~2.3.3" 2387 + }, 2388 + "peerDependencies": { 2389 + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2390 + "jiti": ">=1.21.0", 2391 + "less": "*", 2392 + "lightningcss": "^1.21.0", 2393 + "sass": "*", 2394 + "sass-embedded": "*", 2395 + "stylus": "*", 2396 + "sugarss": "*", 2397 + "terser": "^5.16.0", 2398 + "tsx": "^4.8.1", 2399 + "yaml": "^2.4.2" 2400 + }, 2401 + "peerDependenciesMeta": { 2402 + "@types/node": { 2403 + "optional": true 2404 + }, 2405 + "jiti": { 2406 + "optional": true 2407 + }, 2408 + "less": { 2409 + "optional": true 2410 + }, 2411 + "lightningcss": { 2412 + "optional": true 2413 + }, 2414 + "sass": { 2415 + "optional": true 2416 + }, 2417 + "sass-embedded": { 2418 + "optional": true 2419 + }, 2420 + "stylus": { 2421 + "optional": true 2422 + }, 2423 + "sugarss": { 2424 + "optional": true 2425 + }, 2426 + "terser": { 2427 + "optional": true 2428 + }, 2429 + "tsx": { 2430 + "optional": true 2431 + }, 2432 + "yaml": { 2433 + "optional": true 2434 + } 2435 + } 2436 + }, 2437 + "node_modules/vite-node": { 2438 + "version": "3.0.9", 2439 + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", 2440 + "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", 2441 + "dev": true, 2442 + "license": "MIT", 2443 + "dependencies": { 2444 + "cac": "^6.7.14", 2445 + "debug": "^4.4.0", 2446 + "es-module-lexer": "^1.6.0", 2447 + "pathe": "^2.0.3", 2448 + "vite": "^5.0.0 || ^6.0.0" 2449 + }, 2450 + "bin": { 2451 + "vite-node": "vite-node.mjs" 2452 + }, 2453 + "engines": { 2454 + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2455 + }, 2456 + "funding": { 2457 + "url": "https://opencollective.com/vitest" 2458 + } 2459 + }, 2460 + "node_modules/vitest": { 2461 + "version": "3.0.9", 2462 + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", 2463 + "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", 2464 + "dev": true, 2465 + "license": "MIT", 2466 + "dependencies": { 2467 + "@vitest/expect": "3.0.9", 2468 + "@vitest/mocker": "3.0.9", 2469 + "@vitest/pretty-format": "^3.0.9", 2470 + "@vitest/runner": "3.0.9", 2471 + "@vitest/snapshot": "3.0.9", 2472 + "@vitest/spy": "3.0.9", 2473 + "@vitest/utils": "3.0.9", 2474 + "chai": "^5.2.0", 2475 + "debug": "^4.4.0", 2476 + "expect-type": "^1.1.0", 2477 + "magic-string": "^0.30.17", 2478 + "pathe": "^2.0.3", 2479 + "std-env": "^3.8.0", 2480 + "tinybench": "^2.9.0", 2481 + "tinyexec": "^0.3.2", 2482 + "tinypool": "^1.0.2", 2483 + "tinyrainbow": "^2.0.0", 2484 + "vite": "^5.0.0 || ^6.0.0", 2485 + "vite-node": "3.0.9", 2486 + "why-is-node-running": "^2.3.0" 2487 + }, 2488 + "bin": { 2489 + "vitest": "vitest.mjs" 2490 + }, 2491 + "engines": { 2492 + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2493 + }, 2494 + "funding": { 2495 + "url": "https://opencollective.com/vitest" 2496 + }, 2497 + "peerDependencies": { 2498 + "@edge-runtime/vm": "*", 2499 + "@types/debug": "^4.1.12", 2500 + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2501 + "@vitest/browser": "3.0.9", 2502 + "@vitest/ui": "3.0.9", 2503 + "happy-dom": "*", 2504 + "jsdom": "*" 2505 + }, 2506 + "peerDependenciesMeta": { 2507 + "@edge-runtime/vm": { 2508 + "optional": true 2509 + }, 2510 + "@types/debug": { 2511 + "optional": true 2512 + }, 2513 + "@types/node": { 2514 + "optional": true 2515 + }, 2516 + "@vitest/browser": { 2517 + "optional": true 2518 + }, 2519 + "@vitest/ui": { 2520 + "optional": true 2521 + }, 2522 + "happy-dom": { 2523 + "optional": true 2524 + }, 2525 + "jsdom": { 2526 + "optional": true 2527 + } 2528 + } 2529 + }, 2530 + "node_modules/why-is-node-running": { 2531 + "version": "2.3.0", 2532 + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", 2533 + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", 2534 + "dev": true, 2535 + "license": "MIT", 2536 + "dependencies": { 2537 + "siginfo": "^2.0.0", 2538 + "stackback": "0.0.2" 2539 + }, 2540 + "bin": { 2541 + "why-is-node-running": "cli.js" 2542 + }, 2543 + "engines": { 2544 + "node": ">=8" 2545 + } 2546 + }, 2547 + "node_modules/workerd": { 2548 + "version": "1.20250428.0", 2549 + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250428.0.tgz", 2550 + "integrity": "sha512-JJNWkHkwPQKQdvtM9UORijgYdcdJsihA4SfYjwh02IUQsdMyZ9jizV1sX9yWi9B9ptlohTW8UNHJEATuphGgdg==", 2551 + "dev": true, 2552 + "hasInstallScript": true, 2553 + "license": "Apache-2.0", 2554 + "bin": { 2555 + "workerd": "bin/workerd" 2556 + }, 2557 + "engines": { 2558 + "node": ">=16" 2559 + }, 2560 + "optionalDependencies": { 2561 + "@cloudflare/workerd-darwin-64": "1.20250428.0", 2562 + "@cloudflare/workerd-darwin-arm64": "1.20250428.0", 2563 + "@cloudflare/workerd-linux-64": "1.20250428.0", 2564 + "@cloudflare/workerd-linux-arm64": "1.20250428.0", 2565 + "@cloudflare/workerd-windows-64": "1.20250428.0" 2566 + } 2567 + }, 2568 + "node_modules/wrangler": { 2569 + "version": "4.14.1", 2570 + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.14.1.tgz", 2571 + "integrity": "sha512-EU7IThP7i68TBftJJSveogvWZ5k/WRijcJh3UclDWiWWhDZTPbL6LOJEFhHKqFzHOaC4Y2Aewt48rfTz0e7oCw==", 2572 + "dev": true, 2573 + "license": "MIT OR Apache-2.0", 2574 + "dependencies": { 2575 + "@cloudflare/kv-asset-handler": "0.4.0", 2576 + "@cloudflare/unenv-preset": "2.3.1", 2577 + "blake3-wasm": "2.1.5", 2578 + "esbuild": "0.25.2", 2579 + "miniflare": "4.20250428.1", 2580 + "path-to-regexp": "6.3.0", 2581 + "unenv": "2.0.0-rc.15", 2582 + "workerd": "1.20250428.0" 2583 + }, 2584 + "bin": { 2585 + "wrangler": "bin/wrangler.js", 2586 + "wrangler2": "bin/wrangler.js" 2587 + }, 2588 + "engines": { 2589 + "node": ">=18.0.0" 2590 + }, 2591 + "optionalDependencies": { 2592 + "fsevents": "~2.3.2", 2593 + "sharp": "^0.33.5" 2594 + }, 2595 + "peerDependencies": { 2596 + "@cloudflare/workers-types": "^4.20250428.0" 2597 + }, 2598 + "peerDependenciesMeta": { 2599 + "@cloudflare/workers-types": { 2600 + "optional": true 2601 + } 2602 + } 2603 + }, 2604 + "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": { 2605 + "version": "0.25.2", 2606 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", 2607 + "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", 2608 + "cpu": [ 2609 + "ppc64" 2610 + ], 2611 + "dev": true, 2612 + "license": "MIT", 2613 + "optional": true, 2614 + "os": [ 2615 + "aix" 2616 + ], 2617 + "engines": { 2618 + "node": ">=18" 2619 + } 2620 + }, 2621 + "node_modules/wrangler/node_modules/@esbuild/android-arm": { 2622 + "version": "0.25.2", 2623 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", 2624 + "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", 2625 + "cpu": [ 2626 + "arm" 2627 + ], 2628 + "dev": true, 2629 + "license": "MIT", 2630 + "optional": true, 2631 + "os": [ 2632 + "android" 2633 + ], 2634 + "engines": { 2635 + "node": ">=18" 2636 + } 2637 + }, 2638 + "node_modules/wrangler/node_modules/@esbuild/android-arm64": { 2639 + "version": "0.25.2", 2640 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", 2641 + "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", 2642 + "cpu": [ 2643 + "arm64" 2644 + ], 2645 + "dev": true, 2646 + "license": "MIT", 2647 + "optional": true, 2648 + "os": [ 2649 + "android" 2650 + ], 2651 + "engines": { 2652 + "node": ">=18" 2653 + } 2654 + }, 2655 + "node_modules/wrangler/node_modules/@esbuild/android-x64": { 2656 + "version": "0.25.2", 2657 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", 2658 + "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", 2659 + "cpu": [ 2660 + "x64" 2661 + ], 2662 + "dev": true, 2663 + "license": "MIT", 2664 + "optional": true, 2665 + "os": [ 2666 + "android" 2667 + ], 2668 + "engines": { 2669 + "node": ">=18" 2670 + } 2671 + }, 2672 + "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { 2673 + "version": "0.25.2", 2674 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", 2675 + "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", 2676 + "cpu": [ 2677 + "arm64" 2678 + ], 2679 + "dev": true, 2680 + "license": "MIT", 2681 + "optional": true, 2682 + "os": [ 2683 + "darwin" 2684 + ], 2685 + "engines": { 2686 + "node": ">=18" 2687 + } 2688 + }, 2689 + "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { 2690 + "version": "0.25.2", 2691 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", 2692 + "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", 2693 + "cpu": [ 2694 + "x64" 2695 + ], 2696 + "dev": true, 2697 + "license": "MIT", 2698 + "optional": true, 2699 + "os": [ 2700 + "darwin" 2701 + ], 2702 + "engines": { 2703 + "node": ">=18" 2704 + } 2705 + }, 2706 + "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { 2707 + "version": "0.25.2", 2708 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", 2709 + "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", 2710 + "cpu": [ 2711 + "arm64" 2712 + ], 2713 + "dev": true, 2714 + "license": "MIT", 2715 + "optional": true, 2716 + "os": [ 2717 + "freebsd" 2718 + ], 2719 + "engines": { 2720 + "node": ">=18" 2721 + } 2722 + }, 2723 + "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { 2724 + "version": "0.25.2", 2725 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", 2726 + "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", 2727 + "cpu": [ 2728 + "x64" 2729 + ], 2730 + "dev": true, 2731 + "license": "MIT", 2732 + "optional": true, 2733 + "os": [ 2734 + "freebsd" 2735 + ], 2736 + "engines": { 2737 + "node": ">=18" 2738 + } 2739 + }, 2740 + "node_modules/wrangler/node_modules/@esbuild/linux-arm": { 2741 + "version": "0.25.2", 2742 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", 2743 + "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", 2744 + "cpu": [ 2745 + "arm" 2746 + ], 2747 + "dev": true, 2748 + "license": "MIT", 2749 + "optional": true, 2750 + "os": [ 2751 + "linux" 2752 + ], 2753 + "engines": { 2754 + "node": ">=18" 2755 + } 2756 + }, 2757 + "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { 2758 + "version": "0.25.2", 2759 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", 2760 + "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", 2761 + "cpu": [ 2762 + "arm64" 2763 + ], 2764 + "dev": true, 2765 + "license": "MIT", 2766 + "optional": true, 2767 + "os": [ 2768 + "linux" 2769 + ], 2770 + "engines": { 2771 + "node": ">=18" 2772 + } 2773 + }, 2774 + "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { 2775 + "version": "0.25.2", 2776 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", 2777 + "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", 2778 + "cpu": [ 2779 + "ia32" 2780 + ], 2781 + "dev": true, 2782 + "license": "MIT", 2783 + "optional": true, 2784 + "os": [ 2785 + "linux" 2786 + ], 2787 + "engines": { 2788 + "node": ">=18" 2789 + } 2790 + }, 2791 + "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { 2792 + "version": "0.25.2", 2793 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", 2794 + "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", 2795 + "cpu": [ 2796 + "loong64" 2797 + ], 2798 + "dev": true, 2799 + "license": "MIT", 2800 + "optional": true, 2801 + "os": [ 2802 + "linux" 2803 + ], 2804 + "engines": { 2805 + "node": ">=18" 2806 + } 2807 + }, 2808 + "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { 2809 + "version": "0.25.2", 2810 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", 2811 + "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", 2812 + "cpu": [ 2813 + "mips64el" 2814 + ], 2815 + "dev": true, 2816 + "license": "MIT", 2817 + "optional": true, 2818 + "os": [ 2819 + "linux" 2820 + ], 2821 + "engines": { 2822 + "node": ">=18" 2823 + } 2824 + }, 2825 + "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { 2826 + "version": "0.25.2", 2827 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", 2828 + "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", 2829 + "cpu": [ 2830 + "ppc64" 2831 + ], 2832 + "dev": true, 2833 + "license": "MIT", 2834 + "optional": true, 2835 + "os": [ 2836 + "linux" 2837 + ], 2838 + "engines": { 2839 + "node": ">=18" 2840 + } 2841 + }, 2842 + "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { 2843 + "version": "0.25.2", 2844 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", 2845 + "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", 2846 + "cpu": [ 2847 + "riscv64" 2848 + ], 2849 + "dev": true, 2850 + "license": "MIT", 2851 + "optional": true, 2852 + "os": [ 2853 + "linux" 2854 + ], 2855 + "engines": { 2856 + "node": ">=18" 2857 + } 2858 + }, 2859 + "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { 2860 + "version": "0.25.2", 2861 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", 2862 + "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", 2863 + "cpu": [ 2864 + "s390x" 2865 + ], 2866 + "dev": true, 2867 + "license": "MIT", 2868 + "optional": true, 2869 + "os": [ 2870 + "linux" 2871 + ], 2872 + "engines": { 2873 + "node": ">=18" 2874 + } 2875 + }, 2876 + "node_modules/wrangler/node_modules/@esbuild/linux-x64": { 2877 + "version": "0.25.2", 2878 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", 2879 + "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", 2880 + "cpu": [ 2881 + "x64" 2882 + ], 2883 + "dev": true, 2884 + "license": "MIT", 2885 + "optional": true, 2886 + "os": [ 2887 + "linux" 2888 + ], 2889 + "engines": { 2890 + "node": ">=18" 2891 + } 2892 + }, 2893 + "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": { 2894 + "version": "0.25.2", 2895 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", 2896 + "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", 2897 + "cpu": [ 2898 + "arm64" 2899 + ], 2900 + "dev": true, 2901 + "license": "MIT", 2902 + "optional": true, 2903 + "os": [ 2904 + "netbsd" 2905 + ], 2906 + "engines": { 2907 + "node": ">=18" 2908 + } 2909 + }, 2910 + "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { 2911 + "version": "0.25.2", 2912 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", 2913 + "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", 2914 + "cpu": [ 2915 + "x64" 2916 + ], 2917 + "dev": true, 2918 + "license": "MIT", 2919 + "optional": true, 2920 + "os": [ 2921 + "netbsd" 2922 + ], 2923 + "engines": { 2924 + "node": ">=18" 2925 + } 2926 + }, 2927 + "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": { 2928 + "version": "0.25.2", 2929 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", 2930 + "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", 2931 + "cpu": [ 2932 + "arm64" 2933 + ], 2934 + "dev": true, 2935 + "license": "MIT", 2936 + "optional": true, 2937 + "os": [ 2938 + "openbsd" 2939 + ], 2940 + "engines": { 2941 + "node": ">=18" 2942 + } 2943 + }, 2944 + "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { 2945 + "version": "0.25.2", 2946 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", 2947 + "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", 2948 + "cpu": [ 2949 + "x64" 2950 + ], 2951 + "dev": true, 2952 + "license": "MIT", 2953 + "optional": true, 2954 + "os": [ 2955 + "openbsd" 2956 + ], 2957 + "engines": { 2958 + "node": ">=18" 2959 + } 2960 + }, 2961 + "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { 2962 + "version": "0.25.2", 2963 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", 2964 + "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", 2965 + "cpu": [ 2966 + "x64" 2967 + ], 2968 + "dev": true, 2969 + "license": "MIT", 2970 + "optional": true, 2971 + "os": [ 2972 + "sunos" 2973 + ], 2974 + "engines": { 2975 + "node": ">=18" 2976 + } 2977 + }, 2978 + "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { 2979 + "version": "0.25.2", 2980 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", 2981 + "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", 2982 + "cpu": [ 2983 + "arm64" 2984 + ], 2985 + "dev": true, 2986 + "license": "MIT", 2987 + "optional": true, 2988 + "os": [ 2989 + "win32" 2990 + ], 2991 + "engines": { 2992 + "node": ">=18" 2993 + } 2994 + }, 2995 + "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { 2996 + "version": "0.25.2", 2997 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", 2998 + "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", 2999 + "cpu": [ 3000 + "ia32" 3001 + ], 3002 + "dev": true, 3003 + "license": "MIT", 3004 + "optional": true, 3005 + "os": [ 3006 + "win32" 3007 + ], 3008 + "engines": { 3009 + "node": ">=18" 3010 + } 3011 + }, 3012 + "node_modules/wrangler/node_modules/@esbuild/win32-x64": { 3013 + "version": "0.25.2", 3014 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", 3015 + "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", 3016 + "cpu": [ 3017 + "x64" 3018 + ], 3019 + "dev": true, 3020 + "license": "MIT", 3021 + "optional": true, 3022 + "os": [ 3023 + "win32" 3024 + ], 3025 + "engines": { 3026 + "node": ">=18" 3027 + } 3028 + }, 3029 + "node_modules/wrangler/node_modules/esbuild": { 3030 + "version": "0.25.2", 3031 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", 3032 + "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", 3033 + "dev": true, 3034 + "hasInstallScript": true, 3035 + "license": "MIT", 3036 + "bin": { 3037 + "esbuild": "bin/esbuild" 3038 + }, 3039 + "engines": { 3040 + "node": ">=18" 3041 + }, 3042 + "optionalDependencies": { 3043 + "@esbuild/aix-ppc64": "0.25.2", 3044 + "@esbuild/android-arm": "0.25.2", 3045 + "@esbuild/android-arm64": "0.25.2", 3046 + "@esbuild/android-x64": "0.25.2", 3047 + "@esbuild/darwin-arm64": "0.25.2", 3048 + "@esbuild/darwin-x64": "0.25.2", 3049 + "@esbuild/freebsd-arm64": "0.25.2", 3050 + "@esbuild/freebsd-x64": "0.25.2", 3051 + "@esbuild/linux-arm": "0.25.2", 3052 + "@esbuild/linux-arm64": "0.25.2", 3053 + "@esbuild/linux-ia32": "0.25.2", 3054 + "@esbuild/linux-loong64": "0.25.2", 3055 + "@esbuild/linux-mips64el": "0.25.2", 3056 + "@esbuild/linux-ppc64": "0.25.2", 3057 + "@esbuild/linux-riscv64": "0.25.2", 3058 + "@esbuild/linux-s390x": "0.25.2", 3059 + "@esbuild/linux-x64": "0.25.2", 3060 + "@esbuild/netbsd-arm64": "0.25.2", 3061 + "@esbuild/netbsd-x64": "0.25.2", 3062 + "@esbuild/openbsd-arm64": "0.25.2", 3063 + "@esbuild/openbsd-x64": "0.25.2", 3064 + "@esbuild/sunos-x64": "0.25.2", 3065 + "@esbuild/win32-arm64": "0.25.2", 3066 + "@esbuild/win32-ia32": "0.25.2", 3067 + "@esbuild/win32-x64": "0.25.2" 3068 + } 3069 + }, 3070 + "node_modules/ws": { 3071 + "version": "8.18.0", 3072 + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", 3073 + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", 3074 + "dev": true, 3075 + "license": "MIT", 3076 + "engines": { 3077 + "node": ">=10.0.0" 3078 + }, 3079 + "peerDependencies": { 3080 + "bufferutil": "^4.0.1", 3081 + "utf-8-validate": ">=5.0.2" 3082 + }, 3083 + "peerDependenciesMeta": { 3084 + "bufferutil": { 3085 + "optional": true 3086 + }, 3087 + "utf-8-validate": { 3088 + "optional": true 3089 + } 3090 + } 3091 + }, 3092 + "node_modules/youch": { 3093 + "version": "3.3.4", 3094 + "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.4.tgz", 3095 + "integrity": "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==", 3096 + "dev": true, 3097 + "license": "MIT", 3098 + "dependencies": { 3099 + "cookie": "^0.7.1", 3100 + "mustache": "^4.2.0", 3101 + "stacktracey": "^2.1.8" 3102 + } 3103 + }, 3104 + "node_modules/zod": { 3105 + "version": "3.24.3", 3106 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz", 3107 + "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==", 3108 + "dev": true, 3109 + "license": "MIT", 3110 + "funding": { 3111 + "url": "https://github.com/sponsors/colinhacks" 3112 + } 3113 + } 3114 + } 3024 3115 }
+18 -14
avatar/package.json
··· 1 1 { 2 - "name": "avatar", 3 - "version": "0.0.0", 4 - "private": true, 5 - "scripts": { 6 - "deploy": "wrangler deploy", 7 - "dev": "wrangler dev", 8 - "start": "wrangler dev", 9 - "test": "vitest" 10 - }, 11 - "devDependencies": { 12 - "@cloudflare/vitest-pool-workers": "^0.8.19", 13 - "vitest": "~3.0.7", 14 - "wrangler": "^4.14.1" 15 - } 2 + "name": "avatar", 3 + "version": "0.0.0", 4 + "private": true, 5 + "type": "module", 6 + "scripts": { 7 + "deploy": "wrangler deploy", 8 + "dev": "wrangler dev", 9 + "start": "wrangler dev", 10 + "test": "vitest" 11 + }, 12 + "dependencies": { 13 + "@atcute/identity-resolver": "^1.2.2" 14 + }, 15 + "devDependencies": { 16 + "@cloudflare/vitest-pool-workers": "^0.8.19", 17 + "vitest": "~3.0.7", 18 + "wrangler": "^4.14.1" 19 + } 16 20 }
+156 -9
avatar/src/index.js
··· 1 + import { 2 + LocalActorResolver, 3 + CompositeHandleResolver, 4 + DohJsonHandleResolver, 5 + WellKnownHandleResolver, 6 + CompositeDidDocumentResolver, 7 + PlcDidDocumentResolver, 8 + WebDidDocumentResolver, 9 + } from "@atcute/identity-resolver"; 10 + 11 + // Initialize resolvers for Cloudflare Workers 12 + const handleResolver = new CompositeHandleResolver({ 13 + strategy: "race", 14 + methods: { 15 + dns: new DohJsonHandleResolver({ 16 + dohUrl: "https://cloudflare-dns.com/dns-query", 17 + }), 18 + http: new WellKnownHandleResolver(), 19 + }, 20 + }); 21 + 22 + const didDocumentResolver = new CompositeDidDocumentResolver({ 23 + methods: { 24 + plc: new PlcDidDocumentResolver(), 25 + web: new WebDidDocumentResolver(), 26 + }, 27 + }); 28 + 29 + const actorResolver = new LocalActorResolver({ 30 + handleResolver, 31 + didDocumentResolver, 32 + }); 33 + 1 34 export default { 2 35 async fetch(request, env) { 3 36 // Helper function to generate a color from a string ··· 14 47 return color; 15 48 }; 16 49 50 + // Helper function to fetch Tangled profile from PDS 51 + const getTangledAvatarFromPDS = async (actor) => { 52 + try { 53 + // Resolve the identity 54 + const identity = await actorResolver.resolve(actor); 55 + if (!identity) { 56 + console.log({ 57 + level: "debug", 58 + message: "failed to resolve identity", 59 + actor: actor, 60 + }); 61 + return null; 62 + } 63 + 64 + const did = identity.did; 65 + const pdsEndpoint = identity.pds.replace(/\/$/, ""); // Remove trailing slash 66 + 67 + if (!pdsEndpoint) { 68 + console.log({ 69 + level: "debug", 70 + message: "no PDS endpoint found", 71 + actor: actor, 72 + did: did, 73 + }); 74 + return null; 75 + } 76 + 77 + const profileUrl = `${pdsEndpoint}/xrpc/com.atproto.repo.getRecord?repo=${did}&collection=sh.tangled.actor.profile&rkey=self`; 78 + 79 + // Fetch the Tangled profile record from PDS 80 + const profileResponse = await fetch(profileUrl); 81 + 82 + if (!profileResponse.ok) { 83 + console.log({ 84 + level: "debug", 85 + message: "no Tangled profile found on PDS", 86 + actor: actor, 87 + status: profileResponse.status, 88 + }); 89 + return null; 90 + } 91 + 92 + const profileData = await profileResponse.json(); 93 + const avatarBlob = profileData?.value?.avatar; 94 + 95 + if (!avatarBlob) { 96 + console.log({ 97 + level: "debug", 98 + message: "Tangled profile has no avatar", 99 + actor: actor, 100 + }); 101 + return null; 102 + } 103 + 104 + // Extract CID from blob reference object 105 + // The ref might be an object with $link property or a string 106 + let avatarCID; 107 + if (typeof avatarBlob.ref === "string") { 108 + avatarCID = avatarBlob.ref; 109 + } else if (avatarBlob.ref?.$link) { 110 + avatarCID = avatarBlob.ref.$link; 111 + } else if (typeof avatarBlob === "string") { 112 + avatarCID = avatarBlob; 113 + } 114 + 115 + if (!avatarCID || typeof avatarCID !== "string") { 116 + console.log({ 117 + level: "warn", 118 + message: "could not extract valid CID from avatar blob", 119 + actor: actor, 120 + avatarBlob: avatarBlob, 121 + avatarBlobRef: avatarBlob.ref, 122 + }); 123 + return null; 124 + } 125 + 126 + // Construct blob URL (pdsEndpoint already has trailing slash removed) 127 + const blobUrl = `${pdsEndpoint}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${avatarCID}`; 128 + 129 + return blobUrl; 130 + } catch (e) { 131 + console.log({ 132 + level: "warn", 133 + message: "error fetching Tangled avatar from PDS", 134 + actor: actor, 135 + error: e.message, 136 + }); 137 + return null; 138 + } 139 + }; 140 + 17 141 const url = new URL(request.url); 18 142 const { pathname, searchParams } = url; 19 143 20 144 if (!pathname || pathname === "/") { 21 - return new Response(`This is Tangled's avatar service. It fetches your pretty avatar from Bluesky and caches it on Cloudflare. 22 - You can't use this directly unfortunately since all requests are signed and may only originate from the appview.`); 145 + return new Response( 146 + `This is Tangled's avatar service. It fetches your pretty avatar from your PDS, Bluesky, or generates a placeholder. 147 + You can't use this directly unfortunately since all requests are signed and may only originate from the appview.`, 148 + ); 23 149 } 24 150 25 151 const size = searchParams.get("size"); ··· 68 194 } 69 195 70 196 try { 71 - const profileResponse = await fetch( 72 - `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${actor}`, 73 - ); 74 - const profile = await profileResponse.json(); 75 - const avatar = profile.avatar; 197 + let avatarUrl = null; 198 + 199 + // Try to get Tangled avatar from user's PDS first 200 + avatarUrl = await getTangledAvatarFromPDS(actor); 201 + 202 + // If no Tangled avatar, fall back to Bluesky 203 + if (!avatarUrl) { 204 + console.log({ 205 + level: "debug", 206 + message: "no Tangled avatar, falling back to Bluesky", 207 + actor: actor, 208 + }); 209 + 210 + const profileResponse = await fetch( 211 + `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${actor}`, 212 + ); 76 213 77 - let avatarUrl = profile.avatar; 214 + if (profileResponse.ok) { 215 + const profile = await profileResponse.json(); 216 + avatarUrl = profile.avatar; 217 + } 218 + } 78 219 79 220 if (!avatarUrl) { 80 221 // Generate a random color based on the actor string 222 + console.log({ 223 + level: "debug", 224 + message: "no avatar found, generating placeholder", 225 + actor: actor, 226 + }); 227 + 81 228 const bgColor = stringToColor(actor); 82 229 const size = resizeToTiny ? 32 : 128; 83 230 const svg = `<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg"><rect width="${size}" height="${size}" fill="${bgColor}"/></svg>`; ··· 93 240 return response; 94 241 } 95 242 96 - // Resize if requested 243 + // Fetch and optionally resize the avatar 97 244 let avatarResponse; 98 245 if (resizeToTiny) { 99 246 avatarResponse = await fetch(avatarUrl, {
+13 -13
avatar/wrangler.jsonc
··· 1 1 { 2 - "$schema": "node_modules/wrangler/config-schema.json", 3 - "name": "avatar", 4 - "main": "src/index.js", 5 - "compatibility_date": "2025-05-03", 6 - "observability": { 7 - "enabled": true, 8 - }, 9 - "routes": [ 10 - { 11 - "pattern": "avatar.tangled.sh", 12 - "custom_domain": true, 13 - }, 14 - ], 2 + "$schema": "node_modules/wrangler/config-schema.json", 3 + "name": "avatar", 4 + "main": "src/index.js", 5 + "compatibility_date": "2025-05-03", 6 + "observability": { 7 + "enabled": true, 8 + }, 9 + "routes": [ 10 + { 11 + "pattern": "avatar.tangled.sh", 12 + "custom_domain": true, 13 + }, 14 + ], 15 15 }
+3
flake.nix
··· 284 284 rm -f api/tangled/* 285 285 lexgen --build-file lexicon-build-config.json lexicons 286 286 sed -i.bak 's/\tutil/\/\/\tutil/' api/tangled/* 287 + # lexgen generates incomplete Marshaler/Unmarshaler for union types 288 + find api/tangled/*.go -not -name "cbor_gen.go" -exec \ 289 + sed -i '/^func.*\(MarshalCBOR\|UnmarshalCBOR\)/,/^}/ s/^/\/\/ /' {} + 287 290 ${pkgs.gotools}/bin/goimports -w api/tangled/* 288 291 go run ./cmd/cborgen/ 289 292 lexgen --build-file lexicon-build-config.json lexicons
+3 -3
go.mod
··· 5 5 require ( 6 6 github.com/Blank-Xu/sql-adapter v1.1.1 7 7 github.com/alecthomas/assert/v2 v2.11.0 8 - github.com/alecthomas/chroma/v2 v2.15.0 8 + github.com/alecthomas/chroma/v2 v2.23.1 9 9 github.com/avast/retry-go/v4 v4.6.1 10 10 github.com/blevesearch/bleve/v2 v2.5.3 11 11 github.com/bluekeyes/go-gitdiff v0.8.1 ··· 61 61 github.com/Microsoft/go-winio v0.6.2 // indirect 62 62 github.com/ProtonMail/go-crypto v1.3.0 // indirect 63 63 github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect 64 - github.com/alecthomas/repr v0.4.0 // indirect 64 + github.com/alecthomas/repr v0.5.2 // indirect 65 65 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect 66 66 github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect 67 67 github.com/aymerick/douceur v0.2.0 // indirect ··· 224 224 225 225 replace github.com/bluekeyes/go-gitdiff => tangled.sh/oppi.li/go-gitdiff v0.8.2 226 226 227 - replace github.com/alecthomas/chroma/v2 => github.com/oppiliappan/chroma/v2 v2.19.0 227 + replace github.com/alecthomas/chroma/v2 => github.com/oppiliappan/chroma/v2 v2.24.2 228 228 229 229 // from bluesky-social/indigo 230 230 replace github.com/gocql/gocql => github.com/scylladb/gocql v1.14.4
+4 -3
go.sum
··· 13 13 github.com/RoaringBitmap/roaring/v2 v2.4.5/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0= 14 14 github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= 15 15 github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= 16 - github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= 17 16 github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= 17 + github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= 18 + github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= 18 19 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= 19 20 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= 20 21 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= ··· 412 413 github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= 413 414 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= 414 415 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= 415 - github.com/oppiliappan/chroma/v2 v2.19.0 h1:PN7/pb+6JRKCva30NPTtRJMlrOyzgpPpIroNzy4ekHU= 416 - github.com/oppiliappan/chroma/v2 v2.19.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= 416 + github.com/oppiliappan/chroma/v2 v2.24.2 h1:lHB9tWQxDoHa6sYEDdFep8SX6FPMmAF+ocGUffFwujE= 417 + github.com/oppiliappan/chroma/v2 v2.24.2/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= 417 418 github.com/oppiliappan/go-git/v5 v5.17.0 h1:CuJnpcIDxr0oiNaSHMconovSWnowHznVDG+AhjGuSEo= 418 419 github.com/oppiliappan/go-git/v5 v5.17.0/go.mod h1:q/FE8C3SPMoRN7LoH9vRFiBzidAOBWJPS1CqVS8DN+w= 419 420 github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
+2 -2
input.css
··· 93 93 @apply block text-gray-900 text-sm font-bold py-2 uppercase dark:text-gray-100; 94 94 } 95 95 input { 96 - @apply border border-gray-400 block rounded bg-gray-50 focus:ring-black p-3 dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:ring-gray-400; 96 + @apply p-3 border border-gray-100 block rounded bg-gray-50 focus:outline-none focus:ring-1 focus:ring-gray-200 p-3 dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:ring-gray-400;; 97 97 } 98 98 textarea { 99 - @apply border border-gray-400 block rounded bg-gray-50 focus:ring-black p-3 dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:ring-gray-400; 99 + @apply border border-gray-100 block rounded bg-gray-50 focus:outline-none focus:ring-1 focus:ring-gray-200 p-3 dark:bg-gray-800 dark:border-gray-600 dark:text-white dark:focus:ring-gray-400; 100 100 } 101 101 details summary::-webkit-details-marker { 102 102 display: none;
+7 -3
lexicons/actor/profile.json
··· 8 8 "key": "literal:self", 9 9 "record": { 10 10 "type": "object", 11 - "required": [ 12 - "bluesky" 13 - ], 11 + "required": ["bluesky"], 14 12 "properties": { 13 + "avatar": { 14 + "type": "blob", 15 + "description": "Small image to be displayed next to posts from account. AKA, 'profile picture'", 16 + "accept": ["image/png", "image/jpeg"], 17 + "maxSize": 1000000 18 + }, 15 19 "description": { 16 20 "type": "string", 17 21 "description": "Free-form profile description text.",
+4 -4
nix/gomod2nix.toml
··· 20 20 version = "v2.11.0" 21 21 hash = "sha256-tDJCDKZ0R4qNA7hgMKWrpDyogt1802LCJDBCExxdqaU=" 22 22 [mod."github.com/alecthomas/chroma/v2"] 23 - version = "v2.19.0" 24 - hash = "sha256-dxsu43a+PvHg2jYR0Tfys6a8x6IVR+9oCGAh+fvL3SM=" 23 + version = "v2.24.2" 24 + hash = "sha256-Xz4DLZpn98rwaLmNNztK3PJu9MVxDLSrhJI82ZzyFZo=" 25 25 replaced = "github.com/oppiliappan/chroma/v2" 26 26 [mod."github.com/alecthomas/repr"] 27 - version = "v0.4.0" 28 - hash = "sha256-CyAzMSTfLGHDtfGXi91y7XMVpPUDNOKjsznb+osl9dU=" 27 + version = "v0.5.2" 28 + hash = "sha256-PfIeyHh7xTbDN0g2otuDyUOQqbgS4KftVC1JKZ+6sdM=" 29 29 [mod."github.com/anmitsu/go-shlex"] 30 30 version = "v0.0.0-20200514113438-38f4b401e2be" 31 31 hash = "sha256-L3Ak4X2z7WXq7vMKuiHCOJ29nlpajUQ08Sfb9T0yP54="