forked from tangled.org/core
Monorepo for Tangled

Compare changes

Choose any two refs to compare.

-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"` 23 21 // bluesky: Include link to this account on Bluesky. 24 22 Bluesky bool `json:"bluesky" cborgen:"bluesky"` 25 23 // description: Free-form profile description text.
+1 -44
api/tangled/cbor_gen.go
··· 26 26 } 27 27 28 28 cw := cbg.NewCborWriter(w) 29 - fieldCount := 9 30 - 31 - if t.Avatar == nil { 32 - fieldCount-- 33 - } 29 + fieldCount := 8 34 30 35 31 if t.Description == nil { 36 32 fieldCount-- ··· 148 144 return err 149 145 } 150 146 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 170 147 } 171 148 } 172 149 ··· 451 428 } 452 429 453 430 } 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 - 474 431 } 475 432 // t.Bluesky (bool) (bool) 476 433 case "bluesky":
+1 -9
appview/db/db.go
··· 260 260 did text not null, 261 261 262 262 -- data 263 - avatar text, 264 263 description text not null, 265 264 include_bluesky integer not null default 0, 266 265 location text, ··· 1079 1078 // transfer data, constructing pull_at from pulls table 1080 1079 _, err = tx.Exec(` 1081 1080 insert into pull_submissions_new (id, pull_at, round_number, patch, created) 1082 - select 1081 + select 1083 1082 ps.id, 1084 1083 'at://' || p.owner_did || '/sh.tangled.repo.pull/' || p.rkey, 1085 1084 ps.round_number, ··· 1170 1169 1171 1170 create index if not exists idx_stars_created on stars(created); 1172 1171 create index if not exists idx_stars_subject_at_created on stars(subject_at, created); 1173 - `) 1174 - return err 1175 - }) 1176 - 1177 - orm.RunMigration(conn, logger, "add-avatar-to-profile", func(tx *sql.Tx) error { 1178 - _, err := tx.Exec(` 1179 - alter table profile add column avatar text; 1180 1172 `) 1181 1173 return err 1182 1174 })
+2
appview/db/follow.go
··· 167 167 if err != nil { 168 168 return nil, err 169 169 } 170 + defer rows.Close() 171 + 170 172 for rows.Next() { 171 173 var follow models.Follow 172 174 var followedAt string
+1
appview/db/issues.go
··· 452 452 if err != nil { 453 453 return nil, err 454 454 } 455 + defer rows.Close() 455 456 456 457 for rows.Next() { 457 458 var comment models.IssueComment
+1 -1
appview/db/language.go
··· 28 28 whereClause, 29 29 ) 30 30 rows, err := e.Query(query, args...) 31 - 32 31 if err != nil { 33 32 return nil, fmt.Errorf("failed to execute query: %w ", err) 34 33 } 34 + defer rows.Close() 35 35 36 36 var langs []models.RepoLanguage 37 37 for rows.Next() {
+8 -10
appview/db/profile.go
··· 128 128 _, err = tx.Exec( 129 129 `insert or replace into profile ( 130 130 did, 131 - avatar, 132 131 description, 133 132 include_bluesky, 134 133 location, 135 134 pronouns 136 135 ) 137 - values (?, ?, ?, ?, ?, ?)`, 136 + values (?, ?, ?, ?, ?)`, 138 137 profile.Did, 139 - profile.Avatar, 140 138 profile.Description, 141 139 includeBskyValue, 142 140 profile.Location, ··· 232 230 if err != nil { 233 231 return nil, err 234 232 } 233 + defer rows.Close() 235 234 236 235 profileMap := make(map[string]*models.Profile) 237 236 for rows.Next() { ··· 272 271 if err != nil { 273 272 return nil, err 274 273 } 274 + defer rows.Close() 275 + 275 276 idxs := make(map[string]int) 276 277 for did := range profileMap { 277 278 idxs[did] = 0 ··· 292 293 if err != nil { 293 294 return nil, err 294 295 } 296 + defer rows.Close() 297 + 295 298 idxs = make(map[string]int) 296 299 for did := range profileMap { 297 300 idxs[did] = 0 ··· 314 317 func GetProfile(e Execer, did string) (*models.Profile, error) { 315 318 var profile models.Profile 316 319 var pronouns sql.Null[string] 317 - var avatar sql.Null[string] 318 320 319 321 profile.Did = did 320 322 321 323 includeBluesky := 0 322 324 323 325 err := e.QueryRow( 324 - `select avatar, description, include_bluesky, location, pronouns from profile where did = ?`, 326 + `select description, include_bluesky, location, pronouns from profile where did = ?`, 325 327 did, 326 - ).Scan(&avatar, &profile.Description, &includeBluesky, &profile.Location, &pronouns) 328 + ).Scan(&profile.Description, &includeBluesky, &profile.Location, &pronouns) 327 329 if err == sql.ErrNoRows { 328 330 profile := models.Profile{} 329 331 profile.Did = did ··· 340 342 341 343 if pronouns.Valid { 342 344 profile.Pronouns = pronouns.V 343 - } 344 - 345 - if avatar.Valid { 346 - profile.Avatar = avatar.V 347 345 } 348 346 349 347 rows, err := e.Query(`select link from profile_links where did = ?`, did)
+1
appview/db/registration.go
··· 38 38 if err != nil { 39 39 return nil, err 40 40 } 41 + defer rows.Close() 41 42 42 43 for rows.Next() { 43 44 var createdAt string
+11 -1
appview/db/repos.go
··· 56 56 limitClause, 57 57 ) 58 58 rows, err := e.Query(repoQuery, args...) 59 - 60 59 if err != nil { 61 60 return nil, fmt.Errorf("failed to execute repo query: %w ", err) 62 61 } 62 + defer rows.Close() 63 63 64 64 for rows.Next() { 65 65 var repo models.Repo ··· 128 128 if err != nil { 129 129 return nil, fmt.Errorf("failed to execute labels query: %w ", err) 130 130 } 131 + defer rows.Close() 132 + 131 133 for rows.Next() { 132 134 var repoat, labelat string 133 135 if err := rows.Scan(&repoat, &labelat); err != nil { ··· 165 167 if err != nil { 166 168 return nil, fmt.Errorf("failed to execute lang query: %w ", err) 167 169 } 170 + defer rows.Close() 171 + 168 172 for rows.Next() { 169 173 var repoat, lang string 170 174 if err := rows.Scan(&repoat, &lang); err != nil { ··· 191 195 if err != nil { 192 196 return nil, fmt.Errorf("failed to execute star-count query: %w ", err) 193 197 } 198 + defer rows.Close() 199 + 194 200 for rows.Next() { 195 201 var repoat string 196 202 var count int ··· 220 226 if err != nil { 221 227 return nil, fmt.Errorf("failed to execute issue-count query: %w ", err) 222 228 } 229 + defer rows.Close() 230 + 223 231 for rows.Next() { 224 232 var repoat string 225 233 var open, closed int ··· 261 269 if err != nil { 262 270 return nil, fmt.Errorf("failed to execute pulls-count query: %w ", err) 263 271 } 272 + defer rows.Close() 273 + 264 274 for rows.Next() { 265 275 var repoat string 266 276 var open, merged, closed, deleted int
+1
appview/db/star.go
··· 165 165 if err != nil { 166 166 return nil, err 167 167 } 168 + defer rows.Close() 168 169 169 170 starMap := make(map[string][]models.Star) 170 171 for rows.Next() {
-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 - 293 288 description := "" 294 289 if record.Description != nil { 295 290 description = *record.Description ··· 330 325 331 326 profile := models.Profile{ 332 327 Did: did, 333 - Avatar: avatar, 334 328 Description: description, 335 329 IncludeBluesky: includeBluesky, 336 330 Location: location,
-1
appview/models/profile.go
··· 13 13 Did string 14 14 15 15 // data 16 - Avatar string // CID of the avatar blob 17 16 Description string 18 17 IncludeBluesky bool 19 18 Location string
+67 -57
appview/notify/db/db.go
··· 3 3 import ( 4 4 "context" 5 5 "log" 6 - "maps" 7 6 "slices" 8 7 9 8 "github.com/bluesky-social/indigo/atproto/syntax" ··· 13 12 "tangled.org/core/appview/notify" 14 13 "tangled.org/core/idresolver" 15 14 "tangled.org/core/orm" 15 + "tangled.org/core/sets" 16 16 ) 17 17 18 18 const ( 19 - maxMentions = 5 19 + maxMentions = 8 20 20 ) 21 21 22 22 type databaseNotifier struct { ··· 50 50 } 51 51 52 52 actorDid := syntax.DID(star.Did) 53 - recipients := []syntax.DID{syntax.DID(repo.Did)} 53 + recipients := sets.Singleton(syntax.DID(repo.Did)) 54 54 eventType := models.NotificationTypeRepoStarred 55 55 entityType := "repo" 56 56 entityId := star.RepoAt.String() ··· 75 75 } 76 76 77 77 func (n *databaseNotifier) NewIssue(ctx context.Context, issue *models.Issue, mentions []syntax.DID) { 78 - 79 - // build the recipients list 80 - // - owner of the repo 81 - // - collaborators in the repo 82 - var recipients []syntax.DID 83 - recipients = append(recipients, syntax.DID(issue.Repo.Did)) 84 78 collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", issue.Repo.RepoAt())) 85 79 if err != nil { 86 80 log.Printf("failed to fetch collaborators: %v", err) 87 81 return 88 82 } 83 + 84 + // build the recipients list 85 + // - owner of the repo 86 + // - collaborators in the repo 87 + // - remove users already mentioned 88 + recipients := sets.Singleton(syntax.DID(issue.Repo.Did)) 89 89 for _, c := range collaborators { 90 - recipients = append(recipients, c.SubjectDid) 90 + recipients.Insert(c.SubjectDid) 91 + } 92 + for _, m := range mentions { 93 + recipients.Remove(m) 91 94 } 92 95 93 96 actorDid := syntax.DID(issue.Did) ··· 109 112 ) 110 113 n.notifyEvent( 111 114 actorDid, 112 - mentions, 115 + sets.Collect(slices.Values(mentions)), 113 116 models.NotificationTypeUserMentioned, 114 117 entityType, 115 118 entityId, ··· 131 134 } 132 135 issue := issues[0] 133 136 134 - var recipients []syntax.DID 135 - recipients = append(recipients, syntax.DID(issue.Repo.Did)) 137 + // built the recipients list: 138 + // - the owner of the repo 139 + // - | if the comment is a reply -> everybody on that thread 140 + // | if the comment is a top level -> just the issue owner 141 + // - remove mentioned users from the recipients list 142 + recipients := sets.Singleton(syntax.DID(issue.Repo.Did)) 136 143 137 144 if comment.IsReply() { 138 145 // if this comment is a reply, then notify everybody in that thread 139 146 parentAtUri := *comment.ReplyTo 140 - allThreads := issue.CommentList() 141 147 142 148 // find the parent thread, and add all DIDs from here to the recipient list 143 - for _, t := range allThreads { 149 + for _, t := range issue.CommentList() { 144 150 if t.Self.AtUri().String() == parentAtUri { 145 - recipients = append(recipients, t.Participants()...) 151 + for _, p := range t.Participants() { 152 + recipients.Insert(p) 153 + } 146 154 } 147 155 } 148 156 } else { 149 157 // not a reply, notify just the issue author 150 - recipients = append(recipients, syntax.DID(issue.Did)) 158 + recipients.Insert(syntax.DID(issue.Did)) 159 + } 160 + 161 + for _, m := range mentions { 162 + recipients.Remove(m) 151 163 } 152 164 153 165 actorDid := syntax.DID(comment.Did) ··· 169 181 ) 170 182 n.notifyEvent( 171 183 actorDid, 172 - mentions, 184 + sets.Collect(slices.Values(mentions)), 173 185 models.NotificationTypeUserMentioned, 174 186 entityType, 175 187 entityId, ··· 185 197 186 198 func (n *databaseNotifier) NewFollow(ctx context.Context, follow *models.Follow) { 187 199 actorDid := syntax.DID(follow.UserDid) 188 - recipients := []syntax.DID{syntax.DID(follow.SubjectDid)} 200 + recipients := sets.Singleton(syntax.DID(follow.SubjectDid)) 189 201 eventType := models.NotificationTypeFollowed 190 202 entityType := "follow" 191 203 entityId := follow.UserDid ··· 213 225 log.Printf("NewPull: failed to get repos: %v", err) 214 226 return 215 227 } 216 - 217 - // build the recipients list 218 - // - owner of the repo 219 - // - collaborators in the repo 220 - var recipients []syntax.DID 221 - recipients = append(recipients, syntax.DID(repo.Did)) 222 228 collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", repo.RepoAt())) 223 229 if err != nil { 224 230 log.Printf("failed to fetch collaborators: %v", err) 225 231 return 226 232 } 233 + 234 + // build the recipients list 235 + // - owner of the repo 236 + // - collaborators in the repo 237 + recipients := sets.Singleton(syntax.DID(repo.Did)) 227 238 for _, c := range collaborators { 228 - recipients = append(recipients, c.SubjectDid) 239 + recipients.Insert(c.SubjectDid) 229 240 } 230 241 231 242 actorDid := syntax.DID(pull.OwnerDid) ··· 268 279 // build up the recipients list: 269 280 // - repo owner 270 281 // - all pull participants 271 - var recipients []syntax.DID 272 - recipients = append(recipients, syntax.DID(repo.Did)) 282 + // - remove those already mentioned 283 + recipients := sets.Singleton(syntax.DID(repo.Did)) 273 284 for _, p := range pull.Participants() { 274 - recipients = append(recipients, syntax.DID(p)) 285 + recipients.Insert(syntax.DID(p)) 286 + } 287 + for _, m := range mentions { 288 + recipients.Remove(m) 275 289 } 276 290 277 291 actorDid := syntax.DID(comment.OwnerDid) ··· 295 309 ) 296 310 n.notifyEvent( 297 311 actorDid, 298 - mentions, 312 + sets.Collect(slices.Values(mentions)), 299 313 models.NotificationTypeUserMentioned, 300 314 entityType, 301 315 entityId, ··· 322 336 } 323 337 324 338 func (n *databaseNotifier) NewIssueState(ctx context.Context, actor syntax.DID, issue *models.Issue) { 325 - // build up the recipients list: 326 - // - repo owner 327 - // - repo collaborators 328 - // - all issue participants 329 - var recipients []syntax.DID 330 - recipients = append(recipients, syntax.DID(issue.Repo.Did)) 331 339 collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", issue.Repo.RepoAt())) 332 340 if err != nil { 333 341 log.Printf("failed to fetch collaborators: %v", err) 334 342 return 335 343 } 344 + 345 + // build up the recipients list: 346 + // - repo owner 347 + // - repo collaborators 348 + // - all issue participants 349 + recipients := sets.Singleton(syntax.DID(issue.Repo.Did)) 336 350 for _, c := range collaborators { 337 - recipients = append(recipients, c.SubjectDid) 351 + recipients.Insert(c.SubjectDid) 338 352 } 339 353 for _, p := range issue.Participants() { 340 - recipients = append(recipients, syntax.DID(p)) 354 + recipients.Insert(syntax.DID(p)) 341 355 } 342 356 343 357 entityType := "pull" ··· 373 387 return 374 388 } 375 389 376 - // build up the recipients list: 377 - // - repo owner 378 - // - all pull participants 379 - var recipients []syntax.DID 380 - recipients = append(recipients, syntax.DID(repo.Did)) 381 390 collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", repo.RepoAt())) 382 391 if err != nil { 383 392 log.Printf("failed to fetch collaborators: %v", err) 384 393 return 385 394 } 395 + 396 + // build up the recipients list: 397 + // - repo owner 398 + // - all pull participants 399 + recipients := sets.Singleton(syntax.DID(repo.Did)) 386 400 for _, c := range collaborators { 387 - recipients = append(recipients, c.SubjectDid) 401 + recipients.Insert(c.SubjectDid) 388 402 } 389 403 for _, p := range pull.Participants() { 390 - recipients = append(recipients, syntax.DID(p)) 404 + recipients.Insert(syntax.DID(p)) 391 405 } 392 406 393 407 entityType := "pull" ··· 423 437 424 438 func (n *databaseNotifier) notifyEvent( 425 439 actorDid syntax.DID, 426 - recipients []syntax.DID, 440 + recipients sets.Set[syntax.DID], 427 441 eventType models.NotificationType, 428 442 entityType string, 429 443 entityId string, ··· 431 445 issueId *int64, 432 446 pullId *int64, 433 447 ) { 434 - if eventType == models.NotificationTypeUserMentioned && len(recipients) > maxMentions { 435 - recipients = recipients[:maxMentions] 448 + // if the user is attempting to mention >maxMentions users, this is probably spam, do not mention anybody 449 + if eventType == models.NotificationTypeUserMentioned && recipients.Len() > maxMentions { 450 + return 436 451 } 437 - recipientSet := make(map[syntax.DID]struct{}) 438 - for _, did := range recipients { 439 - // everybody except actor themselves 440 - if did != actorDid { 441 - recipientSet[did] = struct{}{} 442 - } 443 - } 452 + 453 + recipients.Remove(actorDid) 444 454 445 455 prefMap, err := db.GetNotificationPreferences( 446 456 n.db, 447 - orm.FilterIn("user_did", slices.Collect(maps.Keys(recipientSet))), 457 + orm.FilterIn("user_did", slices.Collect(recipients.All())), 448 458 ) 449 459 if err != nil { 450 460 // failed to get prefs for users ··· 460 470 defer tx.Rollback() 461 471 462 472 // filter based on preferences 463 - for recipientDid := range recipientSet { 473 + for recipientDid := range recipients.All() { 464 474 prefs, ok := prefMap[recipientDid] 465 475 if !ok { 466 476 prefs = models.DefaultNotificationPreferences(recipientDid)
-1
appview/notify/merged_notifier.go
··· 39 39 v.Call(in) 40 40 }(n) 41 41 } 42 - wg.Wait() 43 42 } 44 43 45 44 func (m *mergedNotifier) NewRepo(ctx context.Context, repo *models.Repo) {
+7 -23
appview/pages/funcmap.go
··· 25 25 "github.com/dustin/go-humanize" 26 26 "github.com/go-enry/go-enry/v2" 27 27 "github.com/yuin/goldmark" 28 + emoji "github.com/yuin/goldmark-emoji" 28 29 "tangled.org/core/appview/filetree" 29 30 "tangled.org/core/appview/models" 30 31 "tangled.org/core/appview/pages/markup" ··· 261 262 }, 262 263 "description": func(text string) template.HTML { 263 264 p.rctx.RendererType = markup.RendererTypeDefault 264 - htmlString := p.rctx.RenderMarkdownWith(text, goldmark.New()) 265 + htmlString := p.rctx.RenderMarkdownWith(text, goldmark.New( 266 + goldmark.WithExtensions( 267 + emoji.Emoji, 268 + ), 269 + )) 265 270 sanitized := p.rctx.SanitizeDescription(htmlString) 266 271 return template.HTML(sanitized) 267 272 }, ··· 360 365 "fullAvatar": func(handle string) string { 361 366 return p.AvatarUrl(handle, "") 362 367 }, 363 - "placeholderAvatar": func(size string) template.HTML { 364 - sizeClass := "size-6" 365 - iconSize := "size-4" 366 - if size == "tiny" { 367 - sizeClass = "size-6" 368 - iconSize = "size-4" 369 - } else if size == "small" { 370 - sizeClass = "size-8" 371 - iconSize = "size-5" 372 - } else { 373 - sizeClass = "size-12" 374 - iconSize = "size-8" 375 - } 376 - icon, _ := p.icon("user-round", []string{iconSize, "text-gray-400", "dark:text-gray-500"}) 377 - 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)) 378 - }, 379 - "profileAvatarUrl": func(profile *models.Profile, size string) string { 380 - if profile != nil { 381 - return p.AvatarUrl(profile.Did, size) 382 - } 383 - return "" 384 - }, 385 368 "langColor": enry.GetColor, 386 369 "layoutSide": func() string { 387 370 return "col-span-1 md:col-span-2 lg:col-span-3" ··· 421 404 422 405 func (p *Pages) AvatarUrl(handle, size string) string { 423 406 handle = strings.TrimPrefix(handle, "@") 407 + 424 408 handle = p.resolveDid(handle) 425 409 426 410 secret := p.avatar.SharedSecret
+2
appview/pages/markup/markdown.go
··· 13 13 chromahtml "github.com/alecthomas/chroma/v2/formatters/html" 14 14 "github.com/alecthomas/chroma/v2/styles" 15 15 "github.com/yuin/goldmark" 16 + "github.com/yuin/goldmark-emoji" 16 17 highlighting "github.com/yuin/goldmark-highlighting/v2" 17 18 "github.com/yuin/goldmark/ast" 18 19 "github.com/yuin/goldmark/extension" ··· 66 67 ), 67 68 callout.CalloutExtention, 68 69 textension.AtExt, 70 + emoji.Emoji, 69 71 ), 70 72 goldmark.WithParserOptions( 71 73 parser.WithAutoHeadingID(),
+1 -1
appview/pages/pages.go
··· 640 640 } 641 641 642 642 func (p *Pages) StarBtnFragment(w io.Writer, params StarBtnFragmentParams) error { 643 - return p.executePlain("fragments/starBtn", w, params) 643 + return p.executePlain("fragments/starBtn-oob", w, params) 644 644 } 645 645 646 646 type RepoIndexParams struct {
+5
appview/pages/templates/fragments/starBtn-oob.html
··· 1 + {{ define "fragments/starBtn-oob" }} 2 + <div hx-swap-oob='outerHTML:#starBtn[data-star-subject-at="{{ .SubjectAt }}"]'> 3 + {{ template "fragments/starBtn" . }} 4 + </div> 5 + {{ end }}
+1 -3
appview/pages/templates/fragments/starBtn.html
··· 1 1 {{ define "fragments/starBtn" }} 2 + {{/* NOTE: this fragment is always replaced with hx-swap-oob */}} 2 3 <button 3 4 id="starBtn" 4 5 class="btn disabled:opacity-50 disabled:cursor-not-allowed flex gap-2 items-center group" ··· 10 11 {{ end }} 11 12 12 13 hx-trigger="click" 13 - hx-target="this" 14 - hx-swap="outerHTML" 15 - hx-swap-oob='outerHTML:#starBtn[data-star-subject-at="{{ .SubjectAt }}"]' 16 14 hx-disabled-elt="#starBtn" 17 15 > 18 16 {{ if .IsStarred }}
+1 -1
appview/pages/templates/knots/index.html
··· 105 105 {{ define "docsButton" }} 106 106 <a 107 107 class="btn flex items-center gap-2" 108 - href="https://tangled.org/@tangled.org/core/blob/master/docs/spindle/hosting.md"> 108 + href="https://tangled.org/@tangled.org/core/blob/master/docs/knot-hosting.md"> 109 109 {{ i "book" "size-4" }} 110 110 docs 111 111 </a>
+63 -22
appview/pages/templates/layouts/fragments/topbar.html
··· 47 47 {{ end }} 48 48 49 49 {{ define "profileDropdown" }} 50 - <details class="relative inline-block text-left nav-dropdown"> 51 - <summary class="cursor-pointer list-none flex items-center gap-1"> 52 - {{ $user := .Did }} 53 - <img 54 - src="{{ tinyAvatar $user }}" 55 - alt="" 56 - class="rounded-full h-6 w-6 border border-gray-300 dark:border-gray-700" 57 - /> 58 - <span class="hidden md:inline">{{ $user | resolve | truncateAt30 }}</span> 59 - </summary> 60 - <div class="absolute flex flex-col right-0 mt-4 p-4 rounded w-48 bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700"> 61 - <a href="/{{ $user }}">profile</a> 62 - <a href="/{{ $user }}?tab=repos">repositories</a> 63 - <a href="/{{ $user }}?tab=strings">strings</a> 64 - <a href="/settings">settings</a> 50 + {{ $user := .Did }} 51 + <button type="button" popovertarget="navigation-popover" class="site-navigation-dropdown-trigger" aria-label="Open site navigation dropdown"> 52 + <img 53 + src="{{ tinyAvatar $user }}" 54 + alt="" 55 + class="rounded-full h-6 w-6 border border-gray-300 dark:border-gray-700" 56 + /> 57 + </button> 58 + <div popover="auto" id="navigation-popover" class="site-navigation-popover shadow-md border border-gray-200 rounded p-2 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-700"> 59 + <div class="flex gap-2 py-2"> 60 + <img 61 + src="{{ tinyAvatar $user }}" 62 + alt="" 63 + class="rounded-full h-6 w-6 border border-gray-300 dark:border-gray-700" 64 + /> 65 + <p>{{ $user | resolve | truncateAt30 }}</p> 66 + </div> 67 + <hr class="h-1 w-full mb-1 mt-2 dark:border-gray-700" /> 68 + <ul id="navigation-menu-popover"> 69 + <li> 70 + <a href="/{{ $user }}"> 71 + {{ i "user" "w-4 h-4" }} 72 + <span>profile</span> 73 + </a> 74 + </li> 75 + <li> 76 + <a href="/{{ $user }}?tab=repos"> 77 + {{ i "book-marked" "w-4 h-4" }} 78 + <span>repositories</span> 79 + </a> 80 + </li> 81 + <li> 82 + <a href="/{{ $user }}?tab=strings"> 83 + {{ i "spool" "w-4 h-4" }} 84 + <span>strings</span> 85 + </a> 86 + </li> 87 + <li> 88 + <a href="/settings"> 89 + {{ i "settings" "w-4 h-4" }} 90 + <span>settings</span> 91 + </a> 92 + </li> 93 + <hr class="h-1 w-full mb-1 mt-2 dark:border-gray-700" /> 94 + <li> 65 95 <a href="#" 66 - hx-post="/logout" 67 - hx-swap="none" 68 - class="text-red-400 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"> 69 - logout 70 - </a> 71 - </div> 72 - </details> 96 + hx-post="/logout" 97 + hx-swap="none" 98 + class="text-red-400 flex gap-2 items-center hover:bg-red-50 hover:text-red-700 px-2 py-2 rounded-sm dark:hover:bg-red-700 dark:hover:text-red-50"> 99 + {{ i "arrow-right-from-line" "w-4 h-4" }} 100 + <span>logout</span> 101 + </a> 102 + </li> 103 + </ul> 104 + </div> 73 105 74 106 <script> 75 107 document.addEventListener('click', function(event) { ··· 80 112 } 81 113 }); 82 114 }); 115 + 116 + const navigationPopoverLinks = document.querySelectorAll("#navigation-menu-popover li a"); 117 + const currentPageURL = window.location.href 118 + navigationPopoverLinks.forEach(link => { 119 + const navigationPopoverLinkURL = link.href 120 + if (navigationPopoverLinkURL === currentPageURL) { 121 + link.ariaCurrent = "page" 122 + } 123 + }) 83 124 </script> 84 125 {{ end }}
+1 -1
appview/pages/templates/layouts/profilebase.html
··· 2 2 3 3 {{ define "extrameta" }} 4 4 {{ $handle := resolve .Card.UserDid }} 5 - {{ $avatarUrl := profileAvatarUrl .Card.Profile "" }} 5 + {{ $avatarUrl := fullAvatar $handle }} 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 }}" />
+1 -4
appview/pages/templates/repo/commit.html
··· 100 100 {{ if $did }} 101 101 {{ template "user/fragments/picHandleLink" $did }} 102 102 {{ else }} 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> 103 + <a href="mailto:{{ $email }}" class="no-underline hover:underline text-gray-500 dark:text-gray-300">{{ $name }}</a> 107 104 {{ end }} 108 105 {{ end }} 109 106
+1 -1
appview/pages/templates/repo/empty.html
··· 26 26 {{ else if (and .LoggedInUser (eq .LoggedInUser.Did .RepoInfo.OwnerDid)) }} 27 27 {{ $knot := .RepoInfo.Knot }} 28 28 {{ if eq $knot "knot1.tangled.sh" }} 29 - {{ $knot = "tangled.sh" }} 29 + {{ $knot = "tangled.org" }} 30 30 {{ end }} 31 31 <div class="w-full flex place-content-center"> 32 32 <div class="py-6 w-fit flex flex-col gap-4">
+6 -6
appview/pages/templates/repo/fragments/backlinks.html
··· 14 14 <div class="flex gap-2 items-center"> 15 15 {{ if .State.IsClosed }} 16 16 <span class="text-gray-500 dark:text-gray-400"> 17 - {{ i "ban" "w-4 h-4" }} 17 + {{ i "ban" "size-3" }} 18 18 </span> 19 19 {{ else if eq .Kind.String "issues" }} 20 20 <span class="text-green-600 dark:text-green-500"> 21 - {{ i "circle-dot" "w-4 h-4" }} 21 + {{ i "circle-dot" "size-3" }} 22 22 </span> 23 23 {{ else if .State.IsOpen }} 24 24 <span class="text-green-600 dark:text-green-500"> 25 - {{ i "git-pull-request" "w-4 h-4" }} 25 + {{ i "git-pull-request" "size-3" }} 26 26 </span> 27 27 {{ else if .State.IsMerged }} 28 28 <span class="text-purple-600 dark:text-purple-500"> 29 - {{ i "git-merge" "w-4 h-4" }} 29 + {{ i "git-merge" "size-3" }} 30 30 </span> 31 31 {{ else }} 32 32 <span class="text-gray-600 dark:text-gray-300"> 33 - {{ i "git-pull-request-closed" "w-4 h-4" }} 33 + {{ i "git-pull-request-closed" "size-3" }} 34 34 </span> 35 35 {{ end }} 36 - <a href="{{ . }}"><span class="text-gray-500 dark:text-gray-400">#{{ .SubjectId }}</span> {{ .Title }}</a> 36 + <a href="{{ . }}" class="line-clamp-1 text-sm"><span class="text-gray-500 dark:text-gray-400">#{{ .SubjectId }}</span> {{ .Title }}</a> 37 37 </div> 38 38 {{ if not (eq $.RepoInfo.FullName $repoUrl) }} 39 39 <div>
+2 -6
appview/pages/templates/repo/index.html
··· 259 259 {{ define "attribution" }} 260 260 {{ $commit := index . 0 }} 261 261 {{ $map := index . 1 }} 262 - <span class="flex items-center gap-1"> 262 + <span class="flex items-center"> 263 263 {{ $author := index $map $commit.Author.Email }} 264 264 {{ $coauthors := $commit.CoAuthors }} 265 265 {{ $all := list }} ··· 274 274 {{ end }} 275 275 {{ end }} 276 276 277 - {{ if $author }} 278 - {{ template "fragments/tinyAvatarList" (dict "all" $all "classes" "size-6") }} 279 - {{ else }} 280 - {{ placeholderAvatar "tiny" }} 281 - {{ end }} 277 + {{ template "fragments/tinyAvatarList" (dict "all" $all "classes" "size-6") }} 282 278 <a href="{{ if $author }}/{{ $author }}{{ else }}mailto:{{ $commit.Author.Email }}{{ end }}" 283 279 class="no-underline hover:underline"> 284 280 {{ if $author }}{{ resolve $author }}{{ else }}{{ $commit.Author.Name }}{{ end }}
+1 -5
appview/pages/templates/repo/log.html
··· 186 186 {{ end }} 187 187 {{ end }} 188 188 189 - {{ if $author }} 190 - {{ template "fragments/tinyAvatarList" (dict "all" $all "classes" "size-6") }} 191 - {{ else }} 192 - {{ placeholderAvatar "tiny" }} 193 - {{ end }} 189 + {{ template "fragments/tinyAvatarList" (dict "all" $all "classes" "size-6") }} 194 190 <a href="{{ if $author }}/{{ $author }}{{ else }}mailto:{{ $commit.Author.Email }}{{ end }}" 195 191 class="no-underline hover:underline"> 196 192 {{ if $author }}{{ resolve $author }}{{ else }}{{ $commit.Author.Name }}{{ end }}
+1 -1
appview/pages/templates/strings/string.html
··· 17 17 <span class="select-none">/</span> 18 18 <a href="/strings/{{ $ownerId }}/{{ .String.Rkey }}" class="font-bold">{{ .String.Filename }}</a> 19 19 </div> 20 - <div class="flex gap-2 text-base"> 20 + <div class="flex gap-2 items-stretch text-base"> 21 21 {{ if and .LoggedInUser (eq .LoggedInUser.Did .String.Did) }} 22 22 <a class="btn flex items-center gap-2 no-underline hover:no-underline p-2 group" 23 23 hx-boost="true"
-44
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 avatar 10 - </label> 11 - <p class="text-sm text-gray-500 dark:text-gray-400">Select an image (PNG or JPEG, max 1MB)</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 class="flex gap-2 pt-2"> 26 - <button 27 - id="cancel-avatar-btn" 28 - type="button" 29 - popovertarget="avatar-upload-modal" 30 - popovertargetaction="hide" 31 - class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"> 32 - {{ i "x" "size-4" }} 33 - cancel 34 - </button> 35 - <button type="submit" class="btn w-1/2 flex items-center"> 36 - <span class="inline-flex gap-2 items-center">{{ i "upload" "size-4" }} upload</span> 37 - <span id="spinner" class="group"> 38 - {{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 39 - </span> 40 - </button> 41 - </div> 42 - <div id="avatar-error" class="text-red-500 dark:text-red-400"></div> 43 - </form> 44 - {{ end }}
+2 -2
appview/pages/templates/user/fragments/followCard.html
··· 6 6 <img class="object-cover rounded-full p-2" src="{{ fullAvatar $userIdent }}" alt="{{ $userIdent }}" /> 7 7 </div> 8 8 9 - <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-2 w-full"> 9 + <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-2 w-full min-w-0"> 10 10 <div class="flex-1 min-h-0 justify-around flex flex-col"> 11 11 <a href="/{{ $userIdent }}"> 12 12 <span class="font-bold dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full">{{ $userIdent | truncateAt30 }}</span> 13 13 </a> 14 14 {{ with .Profile }} 15 - <p class="text-sm pb-2 md:pb-2">{{.Description}}</p> 15 + <p class="text-sm pb-2 md:pb-2 break-words">{{.Description}}</p> 16 16 {{ end }} 17 17 <div class="text-sm flex items-center gap-2 my-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full"> 18 18 <span class="flex-shrink-0">{{ i "users" "size-4" }}</span>
+3 -17
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="{{ 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 }} 6 + <img class="absolute inset-0 w-full h-full object-cover rounded-full p-2" src="{{ fullAvatar .UserDid }}" /> 16 7 </div> 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 8 </div> 24 9 <div class="col-span-2"> 25 10 <div class="flex items-center flex-row flex-nowrap gap-2"> ··· 51 36 {{ block "followerFollowing" (list $ $userIdent) }} {{ end }} 52 37 </div> 53 38 54 - <div class="flex flex-col gap-2 mb-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full"> 39 + <div class="flex flex-col gap-2 mb-2 overflow-hidden text-ellipsis whitespace-nowrap max-w-full"> 55 40 {{ if .Location }} 56 41 <div class="flex items-center gap-2"> 57 42 <span class="flex-shrink-0">{{ i "map-pin" "size-4" }}</span> ··· 126 111 </div> 127 112 {{ end }} 128 113 {{ end }} 114 +
+2 -4
appview/pages/templates/user/settings/emails.html
··· 62 62 hx-swap="none" 63 63 class="flex flex-col gap-2" 64 64 > 65 - <label for="email-address" class="uppercase p-0"> 66 - add email 67 - </label> 65 + <p class="uppercase p-0">ADD EMAIL</p> 68 66 <p class="text-sm text-gray-500 dark:text-gray-400">Commits using this email will be associated with your profile.</p> 69 67 <input 70 68 type="email" ··· 93 91 <div id="settings-emails-error" class="text-red-500 dark:text-red-400"></div> 94 92 <div id="settings-emails-success" class="text-green-500 dark:text-green-400"></div> 95 93 </form> 96 - {{ end }} 94 + {{ end }}
+2 -4
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 - <label for="key-name" class="uppercase p-0"> 67 - add ssh key 68 - </label> 66 + <p class="uppercase p-0">ADD SSH KEY</p> 69 67 <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> 70 68 <input 71 69 type="text"
+9 -6
appview/pages/templates/user/signup.html
··· 43 43 page to complete your registration. 44 44 </span> 45 45 <div class="w-full mt-4 text-center"> 46 - <div class="cf-turnstile" data-sitekey="{{ .CloudflareSiteKey }}"></div> 46 + <div class="cf-turnstile" data-sitekey="{{ .CloudflareSiteKey }}" data-size="flexible"></div> 47 47 </div> 48 48 <button class="btn text-base w-full my-2 mt-6" type="submit" id="signup-button" tabindex="7" > 49 49 <span>join now</span> 50 50 </button> 51 + <p class="text-sm text-gray-500"> 52 + Already have an AT Protocol account? <a href="/login" class="underline">Login to Tangled</a>. 53 + </p> 54 + 55 + <p id="signup-msg" class="error w-full"></p> 56 + <p class="text-sm text-gray-500 pt-4"> 57 + By signing up, you agree to our <a href="/terms" class="underline">Terms of Service</a> and <a href="/privacy" class="underline">Privacy Policy</a>. 58 + </p> 51 59 </form> 52 - <p class="text-sm text-gray-500"> 53 - Already have an AT Protocol account? <a href="/login" class="underline">Login to Tangled</a>. 54 - </p> 55 - 56 - <p id="signup-msg" class="error w-full"></p> 57 60 </main> 58 61 </body> 59 62 </html>
+8
appview/pulls/pulls.go
··· 1366 1366 s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") 1367 1367 return 1368 1368 } 1369 + 1369 1370 } 1370 1371 1371 1372 if err = tx.Commit(); err != nil { 1372 1373 log.Println("failed to create pull request", err) 1373 1374 s.pages.Notice(w, "pull", "Failed to create pull request. Try again later.") 1374 1375 return 1376 + } 1377 + 1378 + // notify about each pull 1379 + // 1380 + // this is performed after tx.Commit, because it could result in a locked DB otherwise 1381 + for _, p := range stack { 1382 + s.notifier.NewPull(r.Context(), p) 1375 1383 } 1376 1384 1377 1385 ownerSlashRepo := reporesolver.GetBaseRepoPath(r, repo)
+17
appview/state/git_http.go
··· 25 25 26 26 } 27 27 28 + func (s *State) UploadArchive(w http.ResponseWriter, r *http.Request) { 29 + user, ok := r.Context().Value("resolvedId").(identity.Identity) 30 + if !ok { 31 + http.Error(w, "failed to resolve user", http.StatusInternalServerError) 32 + return 33 + } 34 + repo := r.Context().Value("repo").(*models.Repo) 35 + 36 + scheme := "https" 37 + if s.config.Core.Dev { 38 + scheme = "http" 39 + } 40 + 41 + targetURL := fmt.Sprintf("%s://%s/%s/%s/git-upload-archive?%s", scheme, repo.Knot, user.DID, repo.Name, r.URL.RawQuery) 42 + s.proxyRequest(w, r, targetURL) 43 + } 44 + 28 45 func (s *State) UploadPack(w http.ResponseWriter, r *http.Request) { 29 46 user, ok := r.Context().Value("resolvedId").(identity.Identity) 30 47 if !ok {
-124
appview/state/profile.go
··· 737 737 AllRepos: allRepos, 738 738 }) 739 739 } 740 - 741 - func (s *State) UploadProfileAvatar(w http.ResponseWriter, r *http.Request) { 742 - l := s.logger.With("handler", "UploadProfileAvatar") 743 - user := s.oauth.GetUser(r) 744 - l = l.With("did", user.Did) 745 - 746 - // Parse multipart form (10MB max) 747 - if err := r.ParseMultipartForm(10 << 20); err != nil { 748 - l.Error("failed to parse form", "err", err) 749 - w.WriteHeader(http.StatusBadRequest) 750 - fmt.Fprintf(w, "Failed to parse form") 751 - return 752 - } 753 - 754 - file, handler, err := r.FormFile("avatar") 755 - if err != nil { 756 - l.Error("failed to read avatar file", "err", err) 757 - w.WriteHeader(http.StatusBadRequest) 758 - fmt.Fprintf(w, "Failed to read avatar file") 759 - return 760 - } 761 - defer file.Close() 762 - 763 - if handler.Size > 1000000 { 764 - l.Warn("avatar file too large", "size", handler.Size) 765 - w.WriteHeader(http.StatusBadRequest) 766 - fmt.Fprintf(w, "Avatar file too large (max 1MB)") 767 - return 768 - } 769 - 770 - contentType := handler.Header.Get("Content-Type") 771 - if contentType != "image/png" && contentType != "image/jpeg" { 772 - l.Warn("invalid image type", "contentType", contentType) 773 - w.WriteHeader(http.StatusBadRequest) 774 - fmt.Fprintf(w, "Invalid image type (only PNG and JPEG allowed)") 775 - return 776 - } 777 - 778 - client, err := s.oauth.AuthorizedClient(r) 779 - if err != nil { 780 - l.Error("failed to get PDS client", "err", err) 781 - w.WriteHeader(http.StatusInternalServerError) 782 - fmt.Fprintf(w, "Failed to connect to your PDS") 783 - return 784 - } 785 - 786 - uploadBlobResp, err := comatproto.RepoUploadBlob(r.Context(), client, file) 787 - if err != nil { 788 - l.Error("failed to upload avatar blob", "err", err) 789 - w.WriteHeader(http.StatusInternalServerError) 790 - fmt.Fprintf(w, "Failed to upload avatar to your PDS") 791 - return 792 - } 793 - 794 - l.Info("uploaded avatar blob", "cid", uploadBlobResp.Blob.Ref.String()) 795 - 796 - // get current profile record from PDS to get its CID for swap 797 - getRecordResp, err := comatproto.RepoGetRecord(r.Context(), client, "", tangled.ActorProfileNSID, user.Did, "self") 798 - if err != nil { 799 - l.Error("failed to get current profile record", "err", err) 800 - w.WriteHeader(http.StatusInternalServerError) 801 - fmt.Fprintf(w, "Failed to get current profile from your PDS") 802 - return 803 - } 804 - 805 - var profileRecord *tangled.ActorProfile 806 - if getRecordResp.Value != nil { 807 - if val, ok := getRecordResp.Value.Val.(*tangled.ActorProfile); ok { 808 - profileRecord = val 809 - } else { 810 - l.Warn("profile record type assertion failed, creating new record") 811 - profileRecord = &tangled.ActorProfile{} 812 - } 813 - } else { 814 - l.Warn("no existing profile record, creating new record") 815 - profileRecord = &tangled.ActorProfile{} 816 - } 817 - 818 - profileRecord.Avatar = uploadBlobResp.Blob 819 - 820 - _, err = comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 821 - Collection: tangled.ActorProfileNSID, 822 - Repo: user.Did, 823 - Rkey: "self", 824 - Record: &lexutil.LexiconTypeDecoder{Val: profileRecord}, 825 - SwapRecord: getRecordResp.Cid, 826 - }) 827 - 828 - if err != nil { 829 - l.Error("failed to update profile record", "err", err) 830 - w.WriteHeader(http.StatusInternalServerError) 831 - fmt.Fprintf(w, "Failed to update profile on your PDS") 832 - return 833 - } 834 - 835 - l.Info("successfully updated profile with avatar") 836 - 837 - profile, err := db.GetProfile(s.db, user.Did) 838 - if err != nil { 839 - l.Warn("getting profile data from DB", "err", err) 840 - profile = &models.Profile{Did: user.Did} 841 - } 842 - profile.Avatar = uploadBlobResp.Blob.Ref.String() 843 - 844 - tx, err := s.db.BeginTx(r.Context(), nil) 845 - if err != nil { 846 - l.Error("failed to start transaction", "err", err) 847 - s.pages.HxRefresh(w) 848 - w.WriteHeader(http.StatusOK) 849 - return 850 - } 851 - 852 - err = db.UpsertProfile(tx, profile) 853 - if err != nil { 854 - l.Error("failed to update profile in DB", "err", err) 855 - tx.Rollback() 856 - s.pages.HxRefresh(w) 857 - w.WriteHeader(http.StatusOK) 858 - return 859 - } 860 - 861 - w.Header().Set("HX-Redirect", r.Header.Get("Referer")) 862 - w.WriteHeader(http.StatusOK) 863 - }
+1 -1
appview/state/router.go
··· 101 101 102 102 // These routes get proxied to the knot 103 103 r.Get("/info/refs", s.InfoRefs) 104 + r.Post("/git-upload-archive", s.UploadArchive) 104 105 r.Post("/git-upload-pack", s.UploadPack) 105 106 r.Post("/git-receive-pack", s.ReceivePack) 106 107 ··· 162 163 r.Get("/edit-pins", s.EditPinsFragment) 163 164 r.Post("/bio", s.UpdateProfileBio) 164 165 r.Post("/pins", s.UpdateProfilePins) 165 - r.Post("/avatar", s.UploadProfileAvatar) 166 166 }) 167 167 168 168 r.Mount("/settings", s.SettingsRouter())
+3022 -3137
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 - "dependencies": { 11 - "@atproto/identity": "^0.4.1" 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/@atproto/common-web": { 20 - "version": "0.4.7", 21 - "resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.4.7.tgz", 22 - "integrity": "sha512-vjw2+81KPo2/SAbbARGn64Ln+6JTI0FTI4xk8if0ebBfDxFRmHb2oSN1y77hzNq/ybGHqA2mecfhS03pxC5+lg==", 23 - "license": "MIT", 24 - "dependencies": { 25 - "@atproto/lex-data": "0.0.3", 26 - "@atproto/lex-json": "0.0.3", 27 - "zod": "^3.23.8" 28 - } 29 - }, 30 - "node_modules/@atproto/crypto": { 31 - "version": "0.4.5", 32 - "resolved": "https://registry.npmjs.org/@atproto/crypto/-/crypto-0.4.5.tgz", 33 - "integrity": "sha512-n40aKkMoCatP0u9Yvhrdk6fXyOHFDDbkdm4h4HCyWW+KlKl8iXfD5iV+ECq+w5BM+QH25aIpt3/j6EUNerhLxw==", 34 - "license": "MIT", 35 - "dependencies": { 36 - "@noble/curves": "^1.7.0", 37 - "@noble/hashes": "^1.6.1", 38 - "uint8arrays": "3.0.0" 39 - }, 40 - "engines": { 41 - "node": ">=18.7.0" 42 - } 43 - }, 44 - "node_modules/@atproto/identity": { 45 - "version": "0.4.10", 46 - "resolved": "https://registry.npmjs.org/@atproto/identity/-/identity-0.4.10.tgz", 47 - "integrity": "sha512-nQbzDLXOhM8p/wo0cTh5DfMSOSHzj6jizpodX37LJ4S1TZzumSxAjHEZa5Rev3JaoD5uSWMVE0MmKEGWkPPvfQ==", 48 - "license": "MIT", 49 - "dependencies": { 50 - "@atproto/common-web": "^0.4.4", 51 - "@atproto/crypto": "^0.4.4" 52 - }, 53 - "engines": { 54 - "node": ">=18.7.0" 55 - } 56 - }, 57 - "node_modules/@atproto/lex-data": { 58 - "version": "0.0.3", 59 - "resolved": "https://registry.npmjs.org/@atproto/lex-data/-/lex-data-0.0.3.tgz", 60 - "integrity": "sha512-ivo1IpY/EX+RIpxPgCf4cPhQo5bfu4nrpa1vJCt8hCm9SfoonJkDFGa0n4SMw4JnXZoUcGcrJ46L+D8bH6GI2g==", 61 - "license": "MIT", 62 - "dependencies": { 63 - "@atproto/syntax": "0.4.2", 64 - "multiformats": "^9.9.0", 65 - "tslib": "^2.8.1", 66 - "uint8arrays": "3.0.0", 67 - "unicode-segmenter": "^0.14.0" 68 - } 69 - }, 70 - "node_modules/@atproto/lex-json": { 71 - "version": "0.0.3", 72 - "resolved": "https://registry.npmjs.org/@atproto/lex-json/-/lex-json-0.0.3.tgz", 73 - "integrity": "sha512-ZVcY7XlRfdPYvQQ2WroKUepee0+NCovrSXgXURM3Xv+n5jflJCoczguROeRr8sN0xvT0ZbzMrDNHCUYKNnxcjw==", 74 - "license": "MIT", 75 - "dependencies": { 76 - "@atproto/lex-data": "0.0.3", 77 - "tslib": "^2.8.1" 78 - } 79 - }, 80 - "node_modules/@atproto/syntax": { 81 - "version": "0.4.2", 82 - "resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.4.2.tgz", 83 - "integrity": "sha512-X9XSRPinBy/0VQ677j8VXlBsYSsUXaiqxWVpGGxJYsAhugdQRb0jqaVKJFtm6RskeNkV6y9xclSUi9UYG/COrA==", 84 - "license": "MIT" 85 - }, 86 - "node_modules/@cloudflare/kv-asset-handler": { 87 - "version": "0.4.0", 88 - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", 89 - "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", 90 - "dev": true, 91 - "license": "MIT OR Apache-2.0", 92 - "dependencies": { 93 - "mime": "^3.0.0" 94 - }, 95 - "engines": { 96 - "node": ">=18.0.0" 97 - } 98 - }, 99 - "node_modules/@cloudflare/unenv-preset": { 100 - "version": "2.3.1", 101 - "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.3.1.tgz", 102 - "integrity": "sha512-Xq57Qd+ADpt6hibcVBO0uLG9zzRgyRhfCUgBT9s+g3+3Ivg5zDyVgLFy40ES1VdNcu8rPNSivm9A+kGP5IVaPg==", 103 - "dev": true, 104 - "license": "MIT OR Apache-2.0", 105 - "peerDependencies": { 106 - "unenv": "2.0.0-rc.15", 107 - "workerd": "^1.20250320.0" 108 - }, 109 - "peerDependenciesMeta": { 110 - "workerd": { 111 - "optional": true 112 - } 113 - } 114 - }, 115 - "node_modules/@cloudflare/vitest-pool-workers": { 116 - "version": "0.8.24", 117 - "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.8.24.tgz", 118 - "integrity": "sha512-wT2PABJQ9YLYWrVu4CRZOjvmjHkdbMyLTZPU9n/7JEMM3pgG8dY41F1Rj31UsXRQaXX39A/CTPGlk58dcMUysA==", 119 - "dev": true, 120 - "license": "MIT", 121 - "dependencies": { 122 - "birpc": "0.2.14", 123 - "cjs-module-lexer": "^1.2.3", 124 - "devalue": "^4.3.0", 125 - "miniflare": "4.20250428.1", 126 - "semver": "^7.7.1", 127 - "wrangler": "4.14.1", 128 - "zod": "^3.22.3" 129 - }, 130 - "peerDependencies": { 131 - "@vitest/runner": "2.0.x - 3.1.x", 132 - "@vitest/snapshot": "2.0.x - 3.1.x", 133 - "vitest": "2.0.x - 3.1.x" 134 - } 135 - }, 136 - "node_modules/@cloudflare/workerd-darwin-64": { 137 - "version": "1.20250428.0", 138 - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250428.0.tgz", 139 - "integrity": "sha512-6nVe9oV4Hdec6ctzMtW80TiDvNTd2oFPi3VsKqSDVaJSJbL+4b6seyJ7G/UEPI+si6JhHBSLV2/9lNXNGLjClA==", 140 - "cpu": [ 141 - "x64" 142 - ], 143 - "dev": true, 144 - "license": "Apache-2.0", 145 - "optional": true, 146 - "os": [ 147 - "darwin" 148 - ], 149 - "engines": { 150 - "node": ">=16" 151 - } 152 - }, 153 - "node_modules/@cloudflare/workerd-darwin-arm64": { 154 - "version": "1.20250428.0", 155 - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250428.0.tgz", 156 - "integrity": "sha512-/TB7bh7SIJ5f+6r4PHsAz7+9Qal/TK1cJuKFkUno1kqGlZbdrMwH0ATYwlWC/nBFeu2FB3NUolsTntEuy23hnQ==", 157 - "cpu": [ 158 - "arm64" 159 - ], 160 - "dev": true, 161 - "license": "Apache-2.0", 162 - "optional": true, 163 - "os": [ 164 - "darwin" 165 - ], 166 - "engines": { 167 - "node": ">=16" 168 - } 169 - }, 170 - "node_modules/@cloudflare/workerd-linux-64": { 171 - "version": "1.20250428.0", 172 - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250428.0.tgz", 173 - "integrity": "sha512-9eCbj+R3CKqpiXP6DfAA20DxKge+OTj7Hyw3ZewiEhWH9INIHiJwJQYybu4iq9kJEGjnGvxgguLFjSCWm26hgg==", 174 - "cpu": [ 175 - "x64" 176 - ], 177 - "dev": true, 178 - "license": "Apache-2.0", 179 - "optional": true, 180 - "os": [ 181 - "linux" 182 - ], 183 - "engines": { 184 - "node": ">=16" 185 - } 186 - }, 187 - "node_modules/@cloudflare/workerd-linux-arm64": { 188 - "version": "1.20250428.0", 189 - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250428.0.tgz", 190 - "integrity": "sha512-D9NRBnW46nl1EQsP13qfkYb5lbt4C6nxl38SBKY/NOcZAUoHzNB5K0GaK8LxvpkM7X/97ySojlMfR5jh5DNXYQ==", 191 - "cpu": [ 192 - "arm64" 193 - ], 194 - "dev": true, 195 - "license": "Apache-2.0", 196 - "optional": true, 197 - "os": [ 198 - "linux" 199 - ], 200 - "engines": { 201 - "node": ">=16" 202 - } 203 - }, 204 - "node_modules/@cloudflare/workerd-windows-64": { 205 - "version": "1.20250428.0", 206 - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250428.0.tgz", 207 - "integrity": "sha512-RQCRj28eitjKD0tmei6iFOuWqMuHMHdNGEigRmbkmuTlpbWHNAoHikgCzZQ/dkKDdatA76TmcpbyECNf31oaTA==", 208 - "cpu": [ 209 - "x64" 210 - ], 211 - "dev": true, 212 - "license": "Apache-2.0", 213 - "optional": true, 214 - "os": [ 215 - "win32" 216 - ], 217 - "engines": { 218 - "node": ">=16" 219 - } 220 - }, 221 - "node_modules/@cspotcode/source-map-support": { 222 - "version": "0.8.1", 223 - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", 224 - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", 225 - "dev": true, 226 - "license": "MIT", 227 - "dependencies": { 228 - "@jridgewell/trace-mapping": "0.3.9" 229 - }, 230 - "engines": { 231 - "node": ">=12" 232 - } 233 - }, 234 - "node_modules/@emnapi/runtime": { 235 - "version": "1.4.3", 236 - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", 237 - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", 238 - "dev": true, 239 - "license": "MIT", 240 - "optional": true, 241 - "dependencies": { 242 - "tslib": "^2.4.0" 243 - } 244 - }, 245 - "node_modules/@esbuild/aix-ppc64": { 246 - "version": "0.25.3", 247 - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", 248 - "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", 249 - "cpu": [ 250 - "ppc64" 251 - ], 252 - "dev": true, 253 - "license": "MIT", 254 - "optional": true, 255 - "os": [ 256 - "aix" 257 - ], 258 - "engines": { 259 - "node": ">=18" 260 - } 261 - }, 262 - "node_modules/@esbuild/android-arm": { 263 - "version": "0.25.3", 264 - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", 265 - "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", 266 - "cpu": [ 267 - "arm" 268 - ], 269 - "dev": true, 270 - "license": "MIT", 271 - "optional": true, 272 - "os": [ 273 - "android" 274 - ], 275 - "engines": { 276 - "node": ">=18" 277 - } 278 - }, 279 - "node_modules/@esbuild/android-arm64": { 280 - "version": "0.25.3", 281 - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", 282 - "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", 283 - "cpu": [ 284 - "arm64" 285 - ], 286 - "dev": true, 287 - "license": "MIT", 288 - "optional": true, 289 - "os": [ 290 - "android" 291 - ], 292 - "engines": { 293 - "node": ">=18" 294 - } 295 - }, 296 - "node_modules/@esbuild/android-x64": { 297 - "version": "0.25.3", 298 - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", 299 - "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", 300 - "cpu": [ 301 - "x64" 302 - ], 303 - "dev": true, 304 - "license": "MIT", 305 - "optional": true, 306 - "os": [ 307 - "android" 308 - ], 309 - "engines": { 310 - "node": ">=18" 311 - } 312 - }, 313 - "node_modules/@esbuild/darwin-arm64": { 314 - "version": "0.25.3", 315 - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", 316 - "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", 317 - "cpu": [ 318 - "arm64" 319 - ], 320 - "dev": true, 321 - "license": "MIT", 322 - "optional": true, 323 - "os": [ 324 - "darwin" 325 - ], 326 - "engines": { 327 - "node": ">=18" 328 - } 329 - }, 330 - "node_modules/@esbuild/darwin-x64": { 331 - "version": "0.25.3", 332 - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", 333 - "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", 334 - "cpu": [ 335 - "x64" 336 - ], 337 - "dev": true, 338 - "license": "MIT", 339 - "optional": true, 340 - "os": [ 341 - "darwin" 342 - ], 343 - "engines": { 344 - "node": ">=18" 345 - } 346 - }, 347 - "node_modules/@esbuild/freebsd-arm64": { 348 - "version": "0.25.3", 349 - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", 350 - "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", 351 - "cpu": [ 352 - "arm64" 353 - ], 354 - "dev": true, 355 - "license": "MIT", 356 - "optional": true, 357 - "os": [ 358 - "freebsd" 359 - ], 360 - "engines": { 361 - "node": ">=18" 362 - } 363 - }, 364 - "node_modules/@esbuild/freebsd-x64": { 365 - "version": "0.25.3", 366 - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", 367 - "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", 368 - "cpu": [ 369 - "x64" 370 - ], 371 - "dev": true, 372 - "license": "MIT", 373 - "optional": true, 374 - "os": [ 375 - "freebsd" 376 - ], 377 - "engines": { 378 - "node": ">=18" 379 - } 380 - }, 381 - "node_modules/@esbuild/linux-arm": { 382 - "version": "0.25.3", 383 - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", 384 - "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", 385 - "cpu": [ 386 - "arm" 387 - ], 388 - "dev": true, 389 - "license": "MIT", 390 - "optional": true, 391 - "os": [ 392 - "linux" 393 - ], 394 - "engines": { 395 - "node": ">=18" 396 - } 397 - }, 398 - "node_modules/@esbuild/linux-arm64": { 399 - "version": "0.25.3", 400 - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", 401 - "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", 402 - "cpu": [ 403 - "arm64" 404 - ], 405 - "dev": true, 406 - "license": "MIT", 407 - "optional": true, 408 - "os": [ 409 - "linux" 410 - ], 411 - "engines": { 412 - "node": ">=18" 413 - } 414 - }, 415 - "node_modules/@esbuild/linux-ia32": { 416 - "version": "0.25.3", 417 - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", 418 - "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", 419 - "cpu": [ 420 - "ia32" 421 - ], 422 - "dev": true, 423 - "license": "MIT", 424 - "optional": true, 425 - "os": [ 426 - "linux" 427 - ], 428 - "engines": { 429 - "node": ">=18" 430 - } 431 - }, 432 - "node_modules/@esbuild/linux-loong64": { 433 - "version": "0.25.3", 434 - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", 435 - "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", 436 - "cpu": [ 437 - "loong64" 438 - ], 439 - "dev": true, 440 - "license": "MIT", 441 - "optional": true, 442 - "os": [ 443 - "linux" 444 - ], 445 - "engines": { 446 - "node": ">=18" 447 - } 448 - }, 449 - "node_modules/@esbuild/linux-mips64el": { 450 - "version": "0.25.3", 451 - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", 452 - "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", 453 - "cpu": [ 454 - "mips64el" 455 - ], 456 - "dev": true, 457 - "license": "MIT", 458 - "optional": true, 459 - "os": [ 460 - "linux" 461 - ], 462 - "engines": { 463 - "node": ">=18" 464 - } 465 - }, 466 - "node_modules/@esbuild/linux-ppc64": { 467 - "version": "0.25.3", 468 - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", 469 - "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", 470 - "cpu": [ 471 - "ppc64" 472 - ], 473 - "dev": true, 474 - "license": "MIT", 475 - "optional": true, 476 - "os": [ 477 - "linux" 478 - ], 479 - "engines": { 480 - "node": ">=18" 481 - } 482 - }, 483 - "node_modules/@esbuild/linux-riscv64": { 484 - "version": "0.25.3", 485 - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", 486 - "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", 487 - "cpu": [ 488 - "riscv64" 489 - ], 490 - "dev": true, 491 - "license": "MIT", 492 - "optional": true, 493 - "os": [ 494 - "linux" 495 - ], 496 - "engines": { 497 - "node": ">=18" 498 - } 499 - }, 500 - "node_modules/@esbuild/linux-s390x": { 501 - "version": "0.25.3", 502 - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", 503 - "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", 504 - "cpu": [ 505 - "s390x" 506 - ], 507 - "dev": true, 508 - "license": "MIT", 509 - "optional": true, 510 - "os": [ 511 - "linux" 512 - ], 513 - "engines": { 514 - "node": ">=18" 515 - } 516 - }, 517 - "node_modules/@esbuild/linux-x64": { 518 - "version": "0.25.3", 519 - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", 520 - "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", 521 - "cpu": [ 522 - "x64" 523 - ], 524 - "dev": true, 525 - "license": "MIT", 526 - "optional": true, 527 - "os": [ 528 - "linux" 529 - ], 530 - "engines": { 531 - "node": ">=18" 532 - } 533 - }, 534 - "node_modules/@esbuild/netbsd-arm64": { 535 - "version": "0.25.3", 536 - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", 537 - "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", 538 - "cpu": [ 539 - "arm64" 540 - ], 541 - "dev": true, 542 - "license": "MIT", 543 - "optional": true, 544 - "os": [ 545 - "netbsd" 546 - ], 547 - "engines": { 548 - "node": ">=18" 549 - } 550 - }, 551 - "node_modules/@esbuild/netbsd-x64": { 552 - "version": "0.25.3", 553 - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", 554 - "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", 555 - "cpu": [ 556 - "x64" 557 - ], 558 - "dev": true, 559 - "license": "MIT", 560 - "optional": true, 561 - "os": [ 562 - "netbsd" 563 - ], 564 - "engines": { 565 - "node": ">=18" 566 - } 567 - }, 568 - "node_modules/@esbuild/openbsd-arm64": { 569 - "version": "0.25.3", 570 - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", 571 - "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", 572 - "cpu": [ 573 - "arm64" 574 - ], 575 - "dev": true, 576 - "license": "MIT", 577 - "optional": true, 578 - "os": [ 579 - "openbsd" 580 - ], 581 - "engines": { 582 - "node": ">=18" 583 - } 584 - }, 585 - "node_modules/@esbuild/openbsd-x64": { 586 - "version": "0.25.3", 587 - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", 588 - "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", 589 - "cpu": [ 590 - "x64" 591 - ], 592 - "dev": true, 593 - "license": "MIT", 594 - "optional": true, 595 - "os": [ 596 - "openbsd" 597 - ], 598 - "engines": { 599 - "node": ">=18" 600 - } 601 - }, 602 - "node_modules/@esbuild/sunos-x64": { 603 - "version": "0.25.3", 604 - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", 605 - "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", 606 - "cpu": [ 607 - "x64" 608 - ], 609 - "dev": true, 610 - "license": "MIT", 611 - "optional": true, 612 - "os": [ 613 - "sunos" 614 - ], 615 - "engines": { 616 - "node": ">=18" 617 - } 618 - }, 619 - "node_modules/@esbuild/win32-arm64": { 620 - "version": "0.25.3", 621 - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", 622 - "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", 623 - "cpu": [ 624 - "arm64" 625 - ], 626 - "dev": true, 627 - "license": "MIT", 628 - "optional": true, 629 - "os": [ 630 - "win32" 631 - ], 632 - "engines": { 633 - "node": ">=18" 634 - } 635 - }, 636 - "node_modules/@esbuild/win32-ia32": { 637 - "version": "0.25.3", 638 - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", 639 - "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", 640 - "cpu": [ 641 - "ia32" 642 - ], 643 - "dev": true, 644 - "license": "MIT", 645 - "optional": true, 646 - "os": [ 647 - "win32" 648 - ], 649 - "engines": { 650 - "node": ">=18" 651 - } 652 - }, 653 - "node_modules/@esbuild/win32-x64": { 654 - "version": "0.25.3", 655 - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", 656 - "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", 657 - "cpu": [ 658 - "x64" 659 - ], 660 - "dev": true, 661 - "license": "MIT", 662 - "optional": true, 663 - "os": [ 664 - "win32" 665 - ], 666 - "engines": { 667 - "node": ">=18" 668 - } 669 - }, 670 - "node_modules/@fastify/busboy": { 671 - "version": "2.1.1", 672 - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", 673 - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", 674 - "dev": true, 675 - "license": "MIT", 676 - "engines": { 677 - "node": ">=14" 678 - } 679 - }, 680 - "node_modules/@img/sharp-darwin-arm64": { 681 - "version": "0.33.5", 682 - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", 683 - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", 684 - "cpu": [ 685 - "arm64" 686 - ], 687 - "dev": true, 688 - "license": "Apache-2.0", 689 - "optional": true, 690 - "os": [ 691 - "darwin" 692 - ], 693 - "engines": { 694 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 695 - }, 696 - "funding": { 697 - "url": "https://opencollective.com/libvips" 698 - }, 699 - "optionalDependencies": { 700 - "@img/sharp-libvips-darwin-arm64": "1.0.4" 701 - } 702 - }, 703 - "node_modules/@img/sharp-darwin-x64": { 704 - "version": "0.33.5", 705 - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", 706 - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", 707 - "cpu": [ 708 - "x64" 709 - ], 710 - "dev": true, 711 - "license": "Apache-2.0", 712 - "optional": true, 713 - "os": [ 714 - "darwin" 715 - ], 716 - "engines": { 717 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 718 - }, 719 - "funding": { 720 - "url": "https://opencollective.com/libvips" 721 - }, 722 - "optionalDependencies": { 723 - "@img/sharp-libvips-darwin-x64": "1.0.4" 724 - } 725 - }, 726 - "node_modules/@img/sharp-libvips-darwin-arm64": { 727 - "version": "1.0.4", 728 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", 729 - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", 730 - "cpu": [ 731 - "arm64" 732 - ], 733 - "dev": true, 734 - "license": "LGPL-3.0-or-later", 735 - "optional": true, 736 - "os": [ 737 - "darwin" 738 - ], 739 - "funding": { 740 - "url": "https://opencollective.com/libvips" 741 - } 742 - }, 743 - "node_modules/@img/sharp-libvips-darwin-x64": { 744 - "version": "1.0.4", 745 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", 746 - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", 747 - "cpu": [ 748 - "x64" 749 - ], 750 - "dev": true, 751 - "license": "LGPL-3.0-or-later", 752 - "optional": true, 753 - "os": [ 754 - "darwin" 755 - ], 756 - "funding": { 757 - "url": "https://opencollective.com/libvips" 758 - } 759 - }, 760 - "node_modules/@img/sharp-libvips-linux-arm": { 761 - "version": "1.0.5", 762 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", 763 - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", 764 - "cpu": [ 765 - "arm" 766 - ], 767 - "dev": true, 768 - "license": "LGPL-3.0-or-later", 769 - "optional": true, 770 - "os": [ 771 - "linux" 772 - ], 773 - "funding": { 774 - "url": "https://opencollective.com/libvips" 775 - } 776 - }, 777 - "node_modules/@img/sharp-libvips-linux-arm64": { 778 - "version": "1.0.4", 779 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", 780 - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", 781 - "cpu": [ 782 - "arm64" 783 - ], 784 - "dev": true, 785 - "license": "LGPL-3.0-or-later", 786 - "optional": true, 787 - "os": [ 788 - "linux" 789 - ], 790 - "funding": { 791 - "url": "https://opencollective.com/libvips" 792 - } 793 - }, 794 - "node_modules/@img/sharp-libvips-linux-s390x": { 795 - "version": "1.0.4", 796 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", 797 - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", 798 - "cpu": [ 799 - "s390x" 800 - ], 801 - "dev": true, 802 - "license": "LGPL-3.0-or-later", 803 - "optional": true, 804 - "os": [ 805 - "linux" 806 - ], 807 - "funding": { 808 - "url": "https://opencollective.com/libvips" 809 - } 810 - }, 811 - "node_modules/@img/sharp-libvips-linux-x64": { 812 - "version": "1.0.4", 813 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", 814 - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", 815 - "cpu": [ 816 - "x64" 817 - ], 818 - "dev": true, 819 - "license": "LGPL-3.0-or-later", 820 - "optional": true, 821 - "os": [ 822 - "linux" 823 - ], 824 - "funding": { 825 - "url": "https://opencollective.com/libvips" 826 - } 827 - }, 828 - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { 829 - "version": "1.0.4", 830 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", 831 - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", 832 - "cpu": [ 833 - "arm64" 834 - ], 835 - "dev": true, 836 - "license": "LGPL-3.0-or-later", 837 - "optional": true, 838 - "os": [ 839 - "linux" 840 - ], 841 - "funding": { 842 - "url": "https://opencollective.com/libvips" 843 - } 844 - }, 845 - "node_modules/@img/sharp-libvips-linuxmusl-x64": { 846 - "version": "1.0.4", 847 - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", 848 - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", 849 - "cpu": [ 850 - "x64" 851 - ], 852 - "dev": true, 853 - "license": "LGPL-3.0-or-later", 854 - "optional": true, 855 - "os": [ 856 - "linux" 857 - ], 858 - "funding": { 859 - "url": "https://opencollective.com/libvips" 860 - } 861 - }, 862 - "node_modules/@img/sharp-linux-arm": { 863 - "version": "0.33.5", 864 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", 865 - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", 866 - "cpu": [ 867 - "arm" 868 - ], 869 - "dev": true, 870 - "license": "Apache-2.0", 871 - "optional": true, 872 - "os": [ 873 - "linux" 874 - ], 875 - "engines": { 876 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 877 - }, 878 - "funding": { 879 - "url": "https://opencollective.com/libvips" 880 - }, 881 - "optionalDependencies": { 882 - "@img/sharp-libvips-linux-arm": "1.0.5" 883 - } 884 - }, 885 - "node_modules/@img/sharp-linux-arm64": { 886 - "version": "0.33.5", 887 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", 888 - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", 889 - "cpu": [ 890 - "arm64" 891 - ], 892 - "dev": true, 893 - "license": "Apache-2.0", 894 - "optional": true, 895 - "os": [ 896 - "linux" 897 - ], 898 - "engines": { 899 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 900 - }, 901 - "funding": { 902 - "url": "https://opencollective.com/libvips" 903 - }, 904 - "optionalDependencies": { 905 - "@img/sharp-libvips-linux-arm64": "1.0.4" 906 - } 907 - }, 908 - "node_modules/@img/sharp-linux-s390x": { 909 - "version": "0.33.5", 910 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", 911 - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", 912 - "cpu": [ 913 - "s390x" 914 - ], 915 - "dev": true, 916 - "license": "Apache-2.0", 917 - "optional": true, 918 - "os": [ 919 - "linux" 920 - ], 921 - "engines": { 922 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 923 - }, 924 - "funding": { 925 - "url": "https://opencollective.com/libvips" 926 - }, 927 - "optionalDependencies": { 928 - "@img/sharp-libvips-linux-s390x": "1.0.4" 929 - } 930 - }, 931 - "node_modules/@img/sharp-linux-x64": { 932 - "version": "0.33.5", 933 - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", 934 - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", 935 - "cpu": [ 936 - "x64" 937 - ], 938 - "dev": true, 939 - "license": "Apache-2.0", 940 - "optional": true, 941 - "os": [ 942 - "linux" 943 - ], 944 - "engines": { 945 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 946 - }, 947 - "funding": { 948 - "url": "https://opencollective.com/libvips" 949 - }, 950 - "optionalDependencies": { 951 - "@img/sharp-libvips-linux-x64": "1.0.4" 952 - } 953 - }, 954 - "node_modules/@img/sharp-linuxmusl-arm64": { 955 - "version": "0.33.5", 956 - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", 957 - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", 958 - "cpu": [ 959 - "arm64" 960 - ], 961 - "dev": true, 962 - "license": "Apache-2.0", 963 - "optional": true, 964 - "os": [ 965 - "linux" 966 - ], 967 - "engines": { 968 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 969 - }, 970 - "funding": { 971 - "url": "https://opencollective.com/libvips" 972 - }, 973 - "optionalDependencies": { 974 - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" 975 - } 976 - }, 977 - "node_modules/@img/sharp-linuxmusl-x64": { 978 - "version": "0.33.5", 979 - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", 980 - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", 981 - "cpu": [ 982 - "x64" 983 - ], 984 - "dev": true, 985 - "license": "Apache-2.0", 986 - "optional": true, 987 - "os": [ 988 - "linux" 989 - ], 990 - "engines": { 991 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 992 - }, 993 - "funding": { 994 - "url": "https://opencollective.com/libvips" 995 - }, 996 - "optionalDependencies": { 997 - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" 998 - } 999 - }, 1000 - "node_modules/@img/sharp-wasm32": { 1001 - "version": "0.33.5", 1002 - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", 1003 - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", 1004 - "cpu": [ 1005 - "wasm32" 1006 - ], 1007 - "dev": true, 1008 - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", 1009 - "optional": true, 1010 - "dependencies": { 1011 - "@emnapi/runtime": "^1.2.0" 1012 - }, 1013 - "engines": { 1014 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1015 - }, 1016 - "funding": { 1017 - "url": "https://opencollective.com/libvips" 1018 - } 1019 - }, 1020 - "node_modules/@img/sharp-win32-ia32": { 1021 - "version": "0.33.5", 1022 - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", 1023 - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", 1024 - "cpu": [ 1025 - "ia32" 1026 - ], 1027 - "dev": true, 1028 - "license": "Apache-2.0 AND LGPL-3.0-or-later", 1029 - "optional": true, 1030 - "os": [ 1031 - "win32" 1032 - ], 1033 - "engines": { 1034 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1035 - }, 1036 - "funding": { 1037 - "url": "https://opencollective.com/libvips" 1038 - } 1039 - }, 1040 - "node_modules/@img/sharp-win32-x64": { 1041 - "version": "0.33.5", 1042 - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", 1043 - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", 1044 - "cpu": [ 1045 - "x64" 1046 - ], 1047 - "dev": true, 1048 - "license": "Apache-2.0 AND LGPL-3.0-or-later", 1049 - "optional": true, 1050 - "os": [ 1051 - "win32" 1052 - ], 1053 - "engines": { 1054 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1055 - }, 1056 - "funding": { 1057 - "url": "https://opencollective.com/libvips" 1058 - } 1059 - }, 1060 - "node_modules/@jridgewell/resolve-uri": { 1061 - "version": "3.1.2", 1062 - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 1063 - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 1064 - "dev": true, 1065 - "license": "MIT", 1066 - "engines": { 1067 - "node": ">=6.0.0" 1068 - } 1069 - }, 1070 - "node_modules/@jridgewell/sourcemap-codec": { 1071 - "version": "1.5.0", 1072 - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 1073 - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 1074 - "dev": true, 1075 - "license": "MIT" 1076 - }, 1077 - "node_modules/@jridgewell/trace-mapping": { 1078 - "version": "0.3.9", 1079 - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", 1080 - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", 1081 - "dev": true, 1082 - "license": "MIT", 1083 - "dependencies": { 1084 - "@jridgewell/resolve-uri": "^3.0.3", 1085 - "@jridgewell/sourcemap-codec": "^1.4.10" 1086 - } 1087 - }, 1088 - "node_modules/@noble/curves": { 1089 - "version": "1.9.7", 1090 - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", 1091 - "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", 1092 - "license": "MIT", 1093 - "dependencies": { 1094 - "@noble/hashes": "1.8.0" 1095 - }, 1096 - "engines": { 1097 - "node": "^14.21.3 || >=16" 1098 - }, 1099 - "funding": { 1100 - "url": "https://paulmillr.com/funding/" 1101 - } 1102 - }, 1103 - "node_modules/@noble/hashes": { 1104 - "version": "1.8.0", 1105 - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", 1106 - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", 1107 - "license": "MIT", 1108 - "engines": { 1109 - "node": "^14.21.3 || >=16" 1110 - }, 1111 - "funding": { 1112 - "url": "https://paulmillr.com/funding/" 1113 - } 1114 - }, 1115 - "node_modules/@rollup/rollup-android-arm-eabi": { 1116 - "version": "4.40.1", 1117 - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.1.tgz", 1118 - "integrity": "sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==", 1119 - "cpu": [ 1120 - "arm" 1121 - ], 1122 - "dev": true, 1123 - "license": "MIT", 1124 - "optional": true, 1125 - "os": [ 1126 - "android" 1127 - ] 1128 - }, 1129 - "node_modules/@rollup/rollup-android-arm64": { 1130 - "version": "4.40.1", 1131 - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.1.tgz", 1132 - "integrity": "sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==", 1133 - "cpu": [ 1134 - "arm64" 1135 - ], 1136 - "dev": true, 1137 - "license": "MIT", 1138 - "optional": true, 1139 - "os": [ 1140 - "android" 1141 - ] 1142 - }, 1143 - "node_modules/@rollup/rollup-darwin-arm64": { 1144 - "version": "4.40.1", 1145 - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.1.tgz", 1146 - "integrity": "sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==", 1147 - "cpu": [ 1148 - "arm64" 1149 - ], 1150 - "dev": true, 1151 - "license": "MIT", 1152 - "optional": true, 1153 - "os": [ 1154 - "darwin" 1155 - ] 1156 - }, 1157 - "node_modules/@rollup/rollup-darwin-x64": { 1158 - "version": "4.40.1", 1159 - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.1.tgz", 1160 - "integrity": "sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==", 1161 - "cpu": [ 1162 - "x64" 1163 - ], 1164 - "dev": true, 1165 - "license": "MIT", 1166 - "optional": true, 1167 - "os": [ 1168 - "darwin" 1169 - ] 1170 - }, 1171 - "node_modules/@rollup/rollup-freebsd-arm64": { 1172 - "version": "4.40.1", 1173 - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.1.tgz", 1174 - "integrity": "sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==", 1175 - "cpu": [ 1176 - "arm64" 1177 - ], 1178 - "dev": true, 1179 - "license": "MIT", 1180 - "optional": true, 1181 - "os": [ 1182 - "freebsd" 1183 - ] 1184 - }, 1185 - "node_modules/@rollup/rollup-freebsd-x64": { 1186 - "version": "4.40.1", 1187 - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.1.tgz", 1188 - "integrity": "sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==", 1189 - "cpu": [ 1190 - "x64" 1191 - ], 1192 - "dev": true, 1193 - "license": "MIT", 1194 - "optional": true, 1195 - "os": [ 1196 - "freebsd" 1197 - ] 1198 - }, 1199 - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 1200 - "version": "4.40.1", 1201 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.1.tgz", 1202 - "integrity": "sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==", 1203 - "cpu": [ 1204 - "arm" 1205 - ], 1206 - "dev": true, 1207 - "license": "MIT", 1208 - "optional": true, 1209 - "os": [ 1210 - "linux" 1211 - ] 1212 - }, 1213 - "node_modules/@rollup/rollup-linux-arm-musleabihf": { 1214 - "version": "4.40.1", 1215 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.1.tgz", 1216 - "integrity": "sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==", 1217 - "cpu": [ 1218 - "arm" 1219 - ], 1220 - "dev": true, 1221 - "license": "MIT", 1222 - "optional": true, 1223 - "os": [ 1224 - "linux" 1225 - ] 1226 - }, 1227 - "node_modules/@rollup/rollup-linux-arm64-gnu": { 1228 - "version": "4.40.1", 1229 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.1.tgz", 1230 - "integrity": "sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==", 1231 - "cpu": [ 1232 - "arm64" 1233 - ], 1234 - "dev": true, 1235 - "license": "MIT", 1236 - "optional": true, 1237 - "os": [ 1238 - "linux" 1239 - ] 1240 - }, 1241 - "node_modules/@rollup/rollup-linux-arm64-musl": { 1242 - "version": "4.40.1", 1243 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.1.tgz", 1244 - "integrity": "sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==", 1245 - "cpu": [ 1246 - "arm64" 1247 - ], 1248 - "dev": true, 1249 - "license": "MIT", 1250 - "optional": true, 1251 - "os": [ 1252 - "linux" 1253 - ] 1254 - }, 1255 - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 1256 - "version": "4.40.1", 1257 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.1.tgz", 1258 - "integrity": "sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==", 1259 - "cpu": [ 1260 - "loong64" 1261 - ], 1262 - "dev": true, 1263 - "license": "MIT", 1264 - "optional": true, 1265 - "os": [ 1266 - "linux" 1267 - ] 1268 - }, 1269 - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 1270 - "version": "4.40.1", 1271 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.1.tgz", 1272 - "integrity": "sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==", 1273 - "cpu": [ 1274 - "ppc64" 1275 - ], 1276 - "dev": true, 1277 - "license": "MIT", 1278 - "optional": true, 1279 - "os": [ 1280 - "linux" 1281 - ] 1282 - }, 1283 - "node_modules/@rollup/rollup-linux-riscv64-gnu": { 1284 - "version": "4.40.1", 1285 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.1.tgz", 1286 - "integrity": "sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==", 1287 - "cpu": [ 1288 - "riscv64" 1289 - ], 1290 - "dev": true, 1291 - "license": "MIT", 1292 - "optional": true, 1293 - "os": [ 1294 - "linux" 1295 - ] 1296 - }, 1297 - "node_modules/@rollup/rollup-linux-riscv64-musl": { 1298 - "version": "4.40.1", 1299 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.1.tgz", 1300 - "integrity": "sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==", 1301 - "cpu": [ 1302 - "riscv64" 1303 - ], 1304 - "dev": true, 1305 - "license": "MIT", 1306 - "optional": true, 1307 - "os": [ 1308 - "linux" 1309 - ] 1310 - }, 1311 - "node_modules/@rollup/rollup-linux-s390x-gnu": { 1312 - "version": "4.40.1", 1313 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.1.tgz", 1314 - "integrity": "sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==", 1315 - "cpu": [ 1316 - "s390x" 1317 - ], 1318 - "dev": true, 1319 - "license": "MIT", 1320 - "optional": true, 1321 - "os": [ 1322 - "linux" 1323 - ] 1324 - }, 1325 - "node_modules/@rollup/rollup-linux-x64-gnu": { 1326 - "version": "4.40.1", 1327 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.1.tgz", 1328 - "integrity": "sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==", 1329 - "cpu": [ 1330 - "x64" 1331 - ], 1332 - "dev": true, 1333 - "license": "MIT", 1334 - "optional": true, 1335 - "os": [ 1336 - "linux" 1337 - ] 1338 - }, 1339 - "node_modules/@rollup/rollup-linux-x64-musl": { 1340 - "version": "4.40.1", 1341 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.1.tgz", 1342 - "integrity": "sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==", 1343 - "cpu": [ 1344 - "x64" 1345 - ], 1346 - "dev": true, 1347 - "license": "MIT", 1348 - "optional": true, 1349 - "os": [ 1350 - "linux" 1351 - ] 1352 - }, 1353 - "node_modules/@rollup/rollup-win32-arm64-msvc": { 1354 - "version": "4.40.1", 1355 - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.1.tgz", 1356 - "integrity": "sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==", 1357 - "cpu": [ 1358 - "arm64" 1359 - ], 1360 - "dev": true, 1361 - "license": "MIT", 1362 - "optional": true, 1363 - "os": [ 1364 - "win32" 1365 - ] 1366 - }, 1367 - "node_modules/@rollup/rollup-win32-ia32-msvc": { 1368 - "version": "4.40.1", 1369 - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.1.tgz", 1370 - "integrity": "sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==", 1371 - "cpu": [ 1372 - "ia32" 1373 - ], 1374 - "dev": true, 1375 - "license": "MIT", 1376 - "optional": true, 1377 - "os": [ 1378 - "win32" 1379 - ] 1380 - }, 1381 - "node_modules/@rollup/rollup-win32-x64-msvc": { 1382 - "version": "4.40.1", 1383 - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.1.tgz", 1384 - "integrity": "sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==", 1385 - "cpu": [ 1386 - "x64" 1387 - ], 1388 - "dev": true, 1389 - "license": "MIT", 1390 - "optional": true, 1391 - "os": [ 1392 - "win32" 1393 - ] 1394 - }, 1395 - "node_modules/@types/estree": { 1396 - "version": "1.0.7", 1397 - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", 1398 - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", 1399 - "dev": true, 1400 - "license": "MIT" 1401 - }, 1402 - "node_modules/@vitest/expect": { 1403 - "version": "3.0.9", 1404 - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.9.tgz", 1405 - "integrity": "sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==", 1406 - "dev": true, 1407 - "license": "MIT", 1408 - "dependencies": { 1409 - "@vitest/spy": "3.0.9", 1410 - "@vitest/utils": "3.0.9", 1411 - "chai": "^5.2.0", 1412 - "tinyrainbow": "^2.0.0" 1413 - }, 1414 - "funding": { 1415 - "url": "https://opencollective.com/vitest" 1416 - } 1417 - }, 1418 - "node_modules/@vitest/mocker": { 1419 - "version": "3.0.9", 1420 - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.9.tgz", 1421 - "integrity": "sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==", 1422 - "dev": true, 1423 - "license": "MIT", 1424 - "dependencies": { 1425 - "@vitest/spy": "3.0.9", 1426 - "estree-walker": "^3.0.3", 1427 - "magic-string": "^0.30.17" 1428 - }, 1429 - "funding": { 1430 - "url": "https://opencollective.com/vitest" 1431 - }, 1432 - "peerDependencies": { 1433 - "msw": "^2.4.9", 1434 - "vite": "^5.0.0 || ^6.0.0" 1435 - }, 1436 - "peerDependenciesMeta": { 1437 - "msw": { 1438 - "optional": true 1439 - }, 1440 - "vite": { 1441 - "optional": true 1442 - } 1443 - } 1444 - }, 1445 - "node_modules/@vitest/pretty-format": { 1446 - "version": "3.1.2", 1447 - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", 1448 - "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", 1449 - "dev": true, 1450 - "license": "MIT", 1451 - "dependencies": { 1452 - "tinyrainbow": "^2.0.0" 1453 - }, 1454 - "funding": { 1455 - "url": "https://opencollective.com/vitest" 1456 - } 1457 - }, 1458 - "node_modules/@vitest/runner": { 1459 - "version": "3.0.9", 1460 - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.9.tgz", 1461 - "integrity": "sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==", 1462 - "dev": true, 1463 - "license": "MIT", 1464 - "dependencies": { 1465 - "@vitest/utils": "3.0.9", 1466 - "pathe": "^2.0.3" 1467 - }, 1468 - "funding": { 1469 - "url": "https://opencollective.com/vitest" 1470 - } 1471 - }, 1472 - "node_modules/@vitest/snapshot": { 1473 - "version": "3.0.9", 1474 - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.9.tgz", 1475 - "integrity": "sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==", 1476 - "dev": true, 1477 - "license": "MIT", 1478 - "dependencies": { 1479 - "@vitest/pretty-format": "3.0.9", 1480 - "magic-string": "^0.30.17", 1481 - "pathe": "^2.0.3" 1482 - }, 1483 - "funding": { 1484 - "url": "https://opencollective.com/vitest" 1485 - } 1486 - }, 1487 - "node_modules/@vitest/snapshot/node_modules/@vitest/pretty-format": { 1488 - "version": "3.0.9", 1489 - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", 1490 - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", 1491 - "dev": true, 1492 - "license": "MIT", 1493 - "dependencies": { 1494 - "tinyrainbow": "^2.0.0" 1495 - }, 1496 - "funding": { 1497 - "url": "https://opencollective.com/vitest" 1498 - } 1499 - }, 1500 - "node_modules/@vitest/spy": { 1501 - "version": "3.0.9", 1502 - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.9.tgz", 1503 - "integrity": "sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==", 1504 - "dev": true, 1505 - "license": "MIT", 1506 - "dependencies": { 1507 - "tinyspy": "^3.0.2" 1508 - }, 1509 - "funding": { 1510 - "url": "https://opencollective.com/vitest" 1511 - } 1512 - }, 1513 - "node_modules/@vitest/utils": { 1514 - "version": "3.0.9", 1515 - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.9.tgz", 1516 - "integrity": "sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==", 1517 - "dev": true, 1518 - "license": "MIT", 1519 - "dependencies": { 1520 - "@vitest/pretty-format": "3.0.9", 1521 - "loupe": "^3.1.3", 1522 - "tinyrainbow": "^2.0.0" 1523 - }, 1524 - "funding": { 1525 - "url": "https://opencollective.com/vitest" 1526 - } 1527 - }, 1528 - "node_modules/@vitest/utils/node_modules/@vitest/pretty-format": { 1529 - "version": "3.0.9", 1530 - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.9.tgz", 1531 - "integrity": "sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==", 1532 - "dev": true, 1533 - "license": "MIT", 1534 - "dependencies": { 1535 - "tinyrainbow": "^2.0.0" 1536 - }, 1537 - "funding": { 1538 - "url": "https://opencollective.com/vitest" 1539 - } 1540 - }, 1541 - "node_modules/acorn": { 1542 - "version": "8.14.0", 1543 - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", 1544 - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", 1545 - "dev": true, 1546 - "license": "MIT", 1547 - "bin": { 1548 - "acorn": "bin/acorn" 1549 - }, 1550 - "engines": { 1551 - "node": ">=0.4.0" 1552 - } 1553 - }, 1554 - "node_modules/acorn-walk": { 1555 - "version": "8.3.2", 1556 - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", 1557 - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", 1558 - "dev": true, 1559 - "license": "MIT", 1560 - "engines": { 1561 - "node": ">=0.4.0" 1562 - } 1563 - }, 1564 - "node_modules/as-table": { 1565 - "version": "1.0.55", 1566 - "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", 1567 - "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", 1568 - "dev": true, 1569 - "license": "MIT", 1570 - "dependencies": { 1571 - "printable-characters": "^1.0.42" 1572 - } 1573 - }, 1574 - "node_modules/assertion-error": { 1575 - "version": "2.0.1", 1576 - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", 1577 - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", 1578 - "dev": true, 1579 - "license": "MIT", 1580 - "engines": { 1581 - "node": ">=12" 1582 - } 1583 - }, 1584 - "node_modules/birpc": { 1585 - "version": "0.2.14", 1586 - "resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.14.tgz", 1587 - "integrity": "sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA==", 1588 - "dev": true, 1589 - "license": "MIT", 1590 - "funding": { 1591 - "url": "https://github.com/sponsors/antfu" 1592 - } 1593 - }, 1594 - "node_modules/blake3-wasm": { 1595 - "version": "2.1.5", 1596 - "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", 1597 - "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", 1598 - "dev": true, 1599 - "license": "MIT" 1600 - }, 1601 - "node_modules/cac": { 1602 - "version": "6.7.14", 1603 - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 1604 - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 1605 - "dev": true, 1606 - "license": "MIT", 1607 - "engines": { 1608 - "node": ">=8" 1609 - } 1610 - }, 1611 - "node_modules/chai": { 1612 - "version": "5.2.0", 1613 - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", 1614 - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", 1615 - "dev": true, 1616 - "license": "MIT", 1617 - "dependencies": { 1618 - "assertion-error": "^2.0.1", 1619 - "check-error": "^2.1.1", 1620 - "deep-eql": "^5.0.1", 1621 - "loupe": "^3.1.0", 1622 - "pathval": "^2.0.0" 1623 - }, 1624 - "engines": { 1625 - "node": ">=12" 1626 - } 1627 - }, 1628 - "node_modules/check-error": { 1629 - "version": "2.1.1", 1630 - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", 1631 - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", 1632 - "dev": true, 1633 - "license": "MIT", 1634 - "engines": { 1635 - "node": ">= 16" 1636 - } 1637 - }, 1638 - "node_modules/cjs-module-lexer": { 1639 - "version": "1.4.3", 1640 - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", 1641 - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", 1642 - "dev": true, 1643 - "license": "MIT" 1644 - }, 1645 - "node_modules/color": { 1646 - "version": "4.2.3", 1647 - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", 1648 - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", 1649 - "dev": true, 1650 - "license": "MIT", 1651 - "optional": true, 1652 - "dependencies": { 1653 - "color-convert": "^2.0.1", 1654 - "color-string": "^1.9.0" 1655 - }, 1656 - "engines": { 1657 - "node": ">=12.5.0" 1658 - } 1659 - }, 1660 - "node_modules/color-convert": { 1661 - "version": "2.0.1", 1662 - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1663 - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1664 - "dev": true, 1665 - "license": "MIT", 1666 - "optional": true, 1667 - "dependencies": { 1668 - "color-name": "~1.1.4" 1669 - }, 1670 - "engines": { 1671 - "node": ">=7.0.0" 1672 - } 1673 - }, 1674 - "node_modules/color-name": { 1675 - "version": "1.1.4", 1676 - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1677 - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1678 - "dev": true, 1679 - "license": "MIT", 1680 - "optional": true 1681 - }, 1682 - "node_modules/color-string": { 1683 - "version": "1.9.1", 1684 - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", 1685 - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", 1686 - "dev": true, 1687 - "license": "MIT", 1688 - "optional": true, 1689 - "dependencies": { 1690 - "color-name": "^1.0.0", 1691 - "simple-swizzle": "^0.2.2" 1692 - } 1693 - }, 1694 - "node_modules/cookie": { 1695 - "version": "0.7.2", 1696 - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 1697 - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 1698 - "dev": true, 1699 - "license": "MIT", 1700 - "engines": { 1701 - "node": ">= 0.6" 1702 - } 1703 - }, 1704 - "node_modules/data-uri-to-buffer": { 1705 - "version": "2.0.2", 1706 - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", 1707 - "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", 1708 - "dev": true, 1709 - "license": "MIT" 1710 - }, 1711 - "node_modules/debug": { 1712 - "version": "4.4.0", 1713 - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 1714 - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 1715 - "dev": true, 1716 - "license": "MIT", 1717 - "dependencies": { 1718 - "ms": "^2.1.3" 1719 - }, 1720 - "engines": { 1721 - "node": ">=6.0" 1722 - }, 1723 - "peerDependenciesMeta": { 1724 - "supports-color": { 1725 - "optional": true 1726 - } 1727 - } 1728 - }, 1729 - "node_modules/deep-eql": { 1730 - "version": "5.0.2", 1731 - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", 1732 - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", 1733 - "dev": true, 1734 - "license": "MIT", 1735 - "engines": { 1736 - "node": ">=6" 1737 - } 1738 - }, 1739 - "node_modules/defu": { 1740 - "version": "6.1.4", 1741 - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", 1742 - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", 1743 - "dev": true, 1744 - "license": "MIT" 1745 - }, 1746 - "node_modules/detect-libc": { 1747 - "version": "2.0.4", 1748 - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", 1749 - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", 1750 - "dev": true, 1751 - "license": "Apache-2.0", 1752 - "optional": true, 1753 - "engines": { 1754 - "node": ">=8" 1755 - } 1756 - }, 1757 - "node_modules/devalue": { 1758 - "version": "4.3.3", 1759 - "resolved": "https://registry.npmjs.org/devalue/-/devalue-4.3.3.tgz", 1760 - "integrity": "sha512-UH8EL6H2ifcY8TbD2QsxwCC/pr5xSwPvv85LrLXVihmHVC3T3YqTCIwnR5ak0yO1KYqlxrPVOA/JVZJYPy2ATg==", 1761 - "dev": true, 1762 - "license": "MIT" 1763 - }, 1764 - "node_modules/es-module-lexer": { 1765 - "version": "1.7.0", 1766 - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", 1767 - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", 1768 - "dev": true, 1769 - "license": "MIT" 1770 - }, 1771 - "node_modules/esbuild": { 1772 - "version": "0.25.3", 1773 - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", 1774 - "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", 1775 - "dev": true, 1776 - "hasInstallScript": true, 1777 - "license": "MIT", 1778 - "bin": { 1779 - "esbuild": "bin/esbuild" 1780 - }, 1781 - "engines": { 1782 - "node": ">=18" 1783 - }, 1784 - "optionalDependencies": { 1785 - "@esbuild/aix-ppc64": "0.25.3", 1786 - "@esbuild/android-arm": "0.25.3", 1787 - "@esbuild/android-arm64": "0.25.3", 1788 - "@esbuild/android-x64": "0.25.3", 1789 - "@esbuild/darwin-arm64": "0.25.3", 1790 - "@esbuild/darwin-x64": "0.25.3", 1791 - "@esbuild/freebsd-arm64": "0.25.3", 1792 - "@esbuild/freebsd-x64": "0.25.3", 1793 - "@esbuild/linux-arm": "0.25.3", 1794 - "@esbuild/linux-arm64": "0.25.3", 1795 - "@esbuild/linux-ia32": "0.25.3", 1796 - "@esbuild/linux-loong64": "0.25.3", 1797 - "@esbuild/linux-mips64el": "0.25.3", 1798 - "@esbuild/linux-ppc64": "0.25.3", 1799 - "@esbuild/linux-riscv64": "0.25.3", 1800 - "@esbuild/linux-s390x": "0.25.3", 1801 - "@esbuild/linux-x64": "0.25.3", 1802 - "@esbuild/netbsd-arm64": "0.25.3", 1803 - "@esbuild/netbsd-x64": "0.25.3", 1804 - "@esbuild/openbsd-arm64": "0.25.3", 1805 - "@esbuild/openbsd-x64": "0.25.3", 1806 - "@esbuild/sunos-x64": "0.25.3", 1807 - "@esbuild/win32-arm64": "0.25.3", 1808 - "@esbuild/win32-ia32": "0.25.3", 1809 - "@esbuild/win32-x64": "0.25.3" 1810 - } 1811 - }, 1812 - "node_modules/estree-walker": { 1813 - "version": "3.0.3", 1814 - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", 1815 - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", 1816 - "dev": true, 1817 - "license": "MIT", 1818 - "dependencies": { 1819 - "@types/estree": "^1.0.0" 1820 - } 1821 - }, 1822 - "node_modules/exit-hook": { 1823 - "version": "2.2.1", 1824 - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", 1825 - "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", 1826 - "dev": true, 1827 - "license": "MIT", 1828 - "engines": { 1829 - "node": ">=6" 1830 - }, 1831 - "funding": { 1832 - "url": "https://github.com/sponsors/sindresorhus" 1833 - } 1834 - }, 1835 - "node_modules/expect-type": { 1836 - "version": "1.2.1", 1837 - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", 1838 - "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", 1839 - "dev": true, 1840 - "license": "Apache-2.0", 1841 - "engines": { 1842 - "node": ">=12.0.0" 1843 - } 1844 - }, 1845 - "node_modules/exsolve": { 1846 - "version": "1.0.5", 1847 - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", 1848 - "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", 1849 - "dev": true, 1850 - "license": "MIT" 1851 - }, 1852 - "node_modules/fdir": { 1853 - "version": "6.4.4", 1854 - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", 1855 - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", 1856 - "dev": true, 1857 - "license": "MIT", 1858 - "peerDependencies": { 1859 - "picomatch": "^3 || ^4" 1860 - }, 1861 - "peerDependenciesMeta": { 1862 - "picomatch": { 1863 - "optional": true 1864 - } 1865 - } 1866 - }, 1867 - "node_modules/fsevents": { 1868 - "version": "2.3.3", 1869 - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1870 - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1871 - "dev": true, 1872 - "hasInstallScript": true, 1873 - "license": "MIT", 1874 - "optional": true, 1875 - "os": [ 1876 - "darwin" 1877 - ], 1878 - "engines": { 1879 - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1880 - } 1881 - }, 1882 - "node_modules/get-source": { 1883 - "version": "2.0.12", 1884 - "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", 1885 - "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", 1886 - "dev": true, 1887 - "license": "Unlicense", 1888 - "dependencies": { 1889 - "data-uri-to-buffer": "^2.0.0", 1890 - "source-map": "^0.6.1" 1891 - } 1892 - }, 1893 - "node_modules/glob-to-regexp": { 1894 - "version": "0.4.1", 1895 - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", 1896 - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", 1897 - "dev": true, 1898 - "license": "BSD-2-Clause" 1899 - }, 1900 - "node_modules/is-arrayish": { 1901 - "version": "0.3.2", 1902 - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", 1903 - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", 1904 - "dev": true, 1905 - "license": "MIT", 1906 - "optional": true 1907 - }, 1908 - "node_modules/loupe": { 1909 - "version": "3.1.3", 1910 - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", 1911 - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", 1912 - "dev": true, 1913 - "license": "MIT" 1914 - }, 1915 - "node_modules/magic-string": { 1916 - "version": "0.30.17", 1917 - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 1918 - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 1919 - "dev": true, 1920 - "license": "MIT", 1921 - "dependencies": { 1922 - "@jridgewell/sourcemap-codec": "^1.5.0" 1923 - } 1924 - }, 1925 - "node_modules/mime": { 1926 - "version": "3.0.0", 1927 - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", 1928 - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", 1929 - "dev": true, 1930 - "license": "MIT", 1931 - "bin": { 1932 - "mime": "cli.js" 1933 - }, 1934 - "engines": { 1935 - "node": ">=10.0.0" 1936 - } 1937 - }, 1938 - "node_modules/miniflare": { 1939 - "version": "4.20250428.1", 1940 - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20250428.1.tgz", 1941 - "integrity": "sha512-M3qcJXjeAEimHrEeWXEhrJiC3YHB5M3QSqqK67pOTI+lHn0QyVG/2iFUjVJ/nv+i10uxeAEva8GRGeu+tKRCmQ==", 1942 - "dev": true, 1943 - "license": "MIT", 1944 - "dependencies": { 1945 - "@cspotcode/source-map-support": "0.8.1", 1946 - "acorn": "8.14.0", 1947 - "acorn-walk": "8.3.2", 1948 - "exit-hook": "2.2.1", 1949 - "glob-to-regexp": "0.4.1", 1950 - "stoppable": "1.1.0", 1951 - "undici": "^5.28.5", 1952 - "workerd": "1.20250428.0", 1953 - "ws": "8.18.0", 1954 - "youch": "3.3.4", 1955 - "zod": "3.22.3" 1956 - }, 1957 - "bin": { 1958 - "miniflare": "bootstrap.js" 1959 - }, 1960 - "engines": { 1961 - "node": ">=18.0.0" 1962 - } 1963 - }, 1964 - "node_modules/miniflare/node_modules/zod": { 1965 - "version": "3.22.3", 1966 - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", 1967 - "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", 1968 - "dev": true, 1969 - "license": "MIT", 1970 - "funding": { 1971 - "url": "https://github.com/sponsors/colinhacks" 1972 - } 1973 - }, 1974 - "node_modules/ms": { 1975 - "version": "2.1.3", 1976 - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1977 - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1978 - "dev": true, 1979 - "license": "MIT" 1980 - }, 1981 - "node_modules/multiformats": { 1982 - "version": "9.9.0", 1983 - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", 1984 - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", 1985 - "license": "(Apache-2.0 AND MIT)" 1986 - }, 1987 - "node_modules/mustache": { 1988 - "version": "4.2.0", 1989 - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", 1990 - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", 1991 - "dev": true, 1992 - "license": "MIT", 1993 - "bin": { 1994 - "mustache": "bin/mustache" 1995 - } 1996 - }, 1997 - "node_modules/nanoid": { 1998 - "version": "3.3.11", 1999 - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 2000 - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 2001 - "dev": true, 2002 - "funding": [ 2003 - { 2004 - "type": "github", 2005 - "url": "https://github.com/sponsors/ai" 2006 - } 2007 - ], 2008 - "license": "MIT", 2009 - "bin": { 2010 - "nanoid": "bin/nanoid.cjs" 2011 - }, 2012 - "engines": { 2013 - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 2014 - } 2015 - }, 2016 - "node_modules/ohash": { 2017 - "version": "2.0.11", 2018 - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", 2019 - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", 2020 - "dev": true, 2021 - "license": "MIT" 2022 - }, 2023 - "node_modules/path-to-regexp": { 2024 - "version": "6.3.0", 2025 - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", 2026 - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", 2027 - "dev": true, 2028 - "license": "MIT" 2029 - }, 2030 - "node_modules/pathe": { 2031 - "version": "2.0.3", 2032 - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", 2033 - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", 2034 - "dev": true, 2035 - "license": "MIT" 2036 - }, 2037 - "node_modules/pathval": { 2038 - "version": "2.0.0", 2039 - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", 2040 - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", 2041 - "dev": true, 2042 - "license": "MIT", 2043 - "engines": { 2044 - "node": ">= 14.16" 2045 - } 2046 - }, 2047 - "node_modules/picocolors": { 2048 - "version": "1.1.1", 2049 - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 2050 - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 2051 - "dev": true, 2052 - "license": "ISC" 2053 - }, 2054 - "node_modules/picomatch": { 2055 - "version": "4.0.2", 2056 - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", 2057 - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", 2058 - "dev": true, 2059 - "license": "MIT", 2060 - "engines": { 2061 - "node": ">=12" 2062 - }, 2063 - "funding": { 2064 - "url": "https://github.com/sponsors/jonschlinkert" 2065 - } 2066 - }, 2067 - "node_modules/postcss": { 2068 - "version": "8.5.3", 2069 - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", 2070 - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", 2071 - "dev": true, 2072 - "funding": [ 2073 - { 2074 - "type": "opencollective", 2075 - "url": "https://opencollective.com/postcss/" 2076 - }, 2077 - { 2078 - "type": "tidelift", 2079 - "url": "https://tidelift.com/funding/github/npm/postcss" 2080 - }, 2081 - { 2082 - "type": "github", 2083 - "url": "https://github.com/sponsors/ai" 2084 - } 2085 - ], 2086 - "license": "MIT", 2087 - "dependencies": { 2088 - "nanoid": "^3.3.8", 2089 - "picocolors": "^1.1.1", 2090 - "source-map-js": "^1.2.1" 2091 - }, 2092 - "engines": { 2093 - "node": "^10 || ^12 || >=14" 2094 - } 2095 - }, 2096 - "node_modules/printable-characters": { 2097 - "version": "1.0.42", 2098 - "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", 2099 - "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", 2100 - "dev": true, 2101 - "license": "Unlicense" 2102 - }, 2103 - "node_modules/rollup": { 2104 - "version": "4.40.1", 2105 - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.1.tgz", 2106 - "integrity": "sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==", 2107 - "dev": true, 2108 - "license": "MIT", 2109 - "dependencies": { 2110 - "@types/estree": "1.0.7" 2111 - }, 2112 - "bin": { 2113 - "rollup": "dist/bin/rollup" 2114 - }, 2115 - "engines": { 2116 - "node": ">=18.0.0", 2117 - "npm": ">=8.0.0" 2118 - }, 2119 - "optionalDependencies": { 2120 - "@rollup/rollup-android-arm-eabi": "4.40.1", 2121 - "@rollup/rollup-android-arm64": "4.40.1", 2122 - "@rollup/rollup-darwin-arm64": "4.40.1", 2123 - "@rollup/rollup-darwin-x64": "4.40.1", 2124 - "@rollup/rollup-freebsd-arm64": "4.40.1", 2125 - "@rollup/rollup-freebsd-x64": "4.40.1", 2126 - "@rollup/rollup-linux-arm-gnueabihf": "4.40.1", 2127 - "@rollup/rollup-linux-arm-musleabihf": "4.40.1", 2128 - "@rollup/rollup-linux-arm64-gnu": "4.40.1", 2129 - "@rollup/rollup-linux-arm64-musl": "4.40.1", 2130 - "@rollup/rollup-linux-loongarch64-gnu": "4.40.1", 2131 - "@rollup/rollup-linux-powerpc64le-gnu": "4.40.1", 2132 - "@rollup/rollup-linux-riscv64-gnu": "4.40.1", 2133 - "@rollup/rollup-linux-riscv64-musl": "4.40.1", 2134 - "@rollup/rollup-linux-s390x-gnu": "4.40.1", 2135 - "@rollup/rollup-linux-x64-gnu": "4.40.1", 2136 - "@rollup/rollup-linux-x64-musl": "4.40.1", 2137 - "@rollup/rollup-win32-arm64-msvc": "4.40.1", 2138 - "@rollup/rollup-win32-ia32-msvc": "4.40.1", 2139 - "@rollup/rollup-win32-x64-msvc": "4.40.1", 2140 - "fsevents": "~2.3.2" 2141 - } 2142 - }, 2143 - "node_modules/semver": { 2144 - "version": "7.7.1", 2145 - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", 2146 - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", 2147 - "dev": true, 2148 - "license": "ISC", 2149 - "bin": { 2150 - "semver": "bin/semver.js" 2151 - }, 2152 - "engines": { 2153 - "node": ">=10" 2154 - } 2155 - }, 2156 - "node_modules/sharp": { 2157 - "version": "0.33.5", 2158 - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", 2159 - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", 2160 - "dev": true, 2161 - "hasInstallScript": true, 2162 - "license": "Apache-2.0", 2163 - "optional": true, 2164 - "dependencies": { 2165 - "color": "^4.2.3", 2166 - "detect-libc": "^2.0.3", 2167 - "semver": "^7.6.3" 2168 - }, 2169 - "engines": { 2170 - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 2171 - }, 2172 - "funding": { 2173 - "url": "https://opencollective.com/libvips" 2174 - }, 2175 - "optionalDependencies": { 2176 - "@img/sharp-darwin-arm64": "0.33.5", 2177 - "@img/sharp-darwin-x64": "0.33.5", 2178 - "@img/sharp-libvips-darwin-arm64": "1.0.4", 2179 - "@img/sharp-libvips-darwin-x64": "1.0.4", 2180 - "@img/sharp-libvips-linux-arm": "1.0.5", 2181 - "@img/sharp-libvips-linux-arm64": "1.0.4", 2182 - "@img/sharp-libvips-linux-s390x": "1.0.4", 2183 - "@img/sharp-libvips-linux-x64": "1.0.4", 2184 - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", 2185 - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", 2186 - "@img/sharp-linux-arm": "0.33.5", 2187 - "@img/sharp-linux-arm64": "0.33.5", 2188 - "@img/sharp-linux-s390x": "0.33.5", 2189 - "@img/sharp-linux-x64": "0.33.5", 2190 - "@img/sharp-linuxmusl-arm64": "0.33.5", 2191 - "@img/sharp-linuxmusl-x64": "0.33.5", 2192 - "@img/sharp-wasm32": "0.33.5", 2193 - "@img/sharp-win32-ia32": "0.33.5", 2194 - "@img/sharp-win32-x64": "0.33.5" 2195 - } 2196 - }, 2197 - "node_modules/siginfo": { 2198 - "version": "2.0.0", 2199 - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", 2200 - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", 2201 - "dev": true, 2202 - "license": "ISC" 2203 - }, 2204 - "node_modules/simple-swizzle": { 2205 - "version": "0.2.2", 2206 - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", 2207 - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", 2208 - "dev": true, 2209 - "license": "MIT", 2210 - "optional": true, 2211 - "dependencies": { 2212 - "is-arrayish": "^0.3.1" 2213 - } 2214 - }, 2215 - "node_modules/source-map": { 2216 - "version": "0.6.1", 2217 - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2218 - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2219 - "dev": true, 2220 - "license": "BSD-3-Clause", 2221 - "engines": { 2222 - "node": ">=0.10.0" 2223 - } 2224 - }, 2225 - "node_modules/source-map-js": { 2226 - "version": "1.2.1", 2227 - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 2228 - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 2229 - "dev": true, 2230 - "license": "BSD-3-Clause", 2231 - "engines": { 2232 - "node": ">=0.10.0" 2233 - } 2234 - }, 2235 - "node_modules/stackback": { 2236 - "version": "0.0.2", 2237 - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", 2238 - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", 2239 - "dev": true, 2240 - "license": "MIT" 2241 - }, 2242 - "node_modules/stacktracey": { 2243 - "version": "2.1.8", 2244 - "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", 2245 - "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", 2246 - "dev": true, 2247 - "license": "Unlicense", 2248 - "dependencies": { 2249 - "as-table": "^1.0.36", 2250 - "get-source": "^2.0.12" 2251 - } 2252 - }, 2253 - "node_modules/std-env": { 2254 - "version": "3.9.0", 2255 - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", 2256 - "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", 2257 - "dev": true, 2258 - "license": "MIT" 2259 - }, 2260 - "node_modules/stoppable": { 2261 - "version": "1.1.0", 2262 - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", 2263 - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", 2264 - "dev": true, 2265 - "license": "MIT", 2266 - "engines": { 2267 - "node": ">=4", 2268 - "npm": ">=6" 2269 - } 2270 - }, 2271 - "node_modules/tinybench": { 2272 - "version": "2.9.0", 2273 - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", 2274 - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", 2275 - "dev": true, 2276 - "license": "MIT" 2277 - }, 2278 - "node_modules/tinyexec": { 2279 - "version": "0.3.2", 2280 - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", 2281 - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", 2282 - "dev": true, 2283 - "license": "MIT" 2284 - }, 2285 - "node_modules/tinyglobby": { 2286 - "version": "0.2.13", 2287 - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", 2288 - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", 2289 - "dev": true, 2290 - "license": "MIT", 2291 - "dependencies": { 2292 - "fdir": "^6.4.4", 2293 - "picomatch": "^4.0.2" 2294 - }, 2295 - "engines": { 2296 - "node": ">=12.0.0" 2297 - }, 2298 - "funding": { 2299 - "url": "https://github.com/sponsors/SuperchupuDev" 2300 - } 2301 - }, 2302 - "node_modules/tinypool": { 2303 - "version": "1.0.2", 2304 - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", 2305 - "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", 2306 - "dev": true, 2307 - "license": "MIT", 2308 - "engines": { 2309 - "node": "^18.0.0 || >=20.0.0" 2310 - } 2311 - }, 2312 - "node_modules/tinyrainbow": { 2313 - "version": "2.0.0", 2314 - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", 2315 - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", 2316 - "dev": true, 2317 - "license": "MIT", 2318 - "engines": { 2319 - "node": ">=14.0.0" 2320 - } 2321 - }, 2322 - "node_modules/tinyspy": { 2323 - "version": "3.0.2", 2324 - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", 2325 - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", 2326 - "dev": true, 2327 - "license": "MIT", 2328 - "engines": { 2329 - "node": ">=14.0.0" 2330 - } 2331 - }, 2332 - "node_modules/tslib": { 2333 - "version": "2.8.1", 2334 - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 2335 - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 2336 - "license": "0BSD" 2337 - }, 2338 - "node_modules/ufo": { 2339 - "version": "1.6.1", 2340 - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", 2341 - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", 2342 - "dev": true, 2343 - "license": "MIT" 2344 - }, 2345 - "node_modules/uint8arrays": { 2346 - "version": "3.0.0", 2347 - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", 2348 - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", 2349 - "license": "MIT", 2350 - "dependencies": { 2351 - "multiformats": "^9.4.2" 2352 - } 2353 - }, 2354 - "node_modules/undici": { 2355 - "version": "5.29.0", 2356 - "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", 2357 - "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", 2358 - "dev": true, 2359 - "license": "MIT", 2360 - "dependencies": { 2361 - "@fastify/busboy": "^2.0.0" 2362 - }, 2363 - "engines": { 2364 - "node": ">=14.0" 2365 - } 2366 - }, 2367 - "node_modules/unenv": { 2368 - "version": "2.0.0-rc.15", 2369 - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.15.tgz", 2370 - "integrity": "sha512-J/rEIZU8w6FOfLNz/hNKsnY+fFHWnu9MH4yRbSZF3xbbGHovcetXPs7sD+9p8L6CeNC//I9bhRYAOsBt2u7/OA==", 2371 - "dev": true, 2372 - "license": "MIT", 2373 - "dependencies": { 2374 - "defu": "^6.1.4", 2375 - "exsolve": "^1.0.4", 2376 - "ohash": "^2.0.11", 2377 - "pathe": "^2.0.3", 2378 - "ufo": "^1.5.4" 2379 - } 2380 - }, 2381 - "node_modules/unicode-segmenter": { 2382 - "version": "0.14.4", 2383 - "resolved": "https://registry.npmjs.org/unicode-segmenter/-/unicode-segmenter-0.14.4.tgz", 2384 - "integrity": "sha512-pR5VCiCrLrKOL6FRW61jnk9+wyMtKKowq+jyFY9oc6uHbWKhDL4yVRiI4YZPksGMK72Pahh8m0cn/0JvbDDyJg==", 2385 - "license": "MIT" 2386 - }, 2387 - "node_modules/vite": { 2388 - "version": "6.3.4", 2389 - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.4.tgz", 2390 - "integrity": "sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==", 2391 - "dev": true, 2392 - "license": "MIT", 2393 - "dependencies": { 2394 - "esbuild": "^0.25.0", 2395 - "fdir": "^6.4.4", 2396 - "picomatch": "^4.0.2", 2397 - "postcss": "^8.5.3", 2398 - "rollup": "^4.34.9", 2399 - "tinyglobby": "^0.2.13" 2400 - }, 2401 - "bin": { 2402 - "vite": "bin/vite.js" 2403 - }, 2404 - "engines": { 2405 - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2406 - }, 2407 - "funding": { 2408 - "url": "https://github.com/vitejs/vite?sponsor=1" 2409 - }, 2410 - "optionalDependencies": { 2411 - "fsevents": "~2.3.3" 2412 - }, 2413 - "peerDependencies": { 2414 - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2415 - "jiti": ">=1.21.0", 2416 - "less": "*", 2417 - "lightningcss": "^1.21.0", 2418 - "sass": "*", 2419 - "sass-embedded": "*", 2420 - "stylus": "*", 2421 - "sugarss": "*", 2422 - "terser": "^5.16.0", 2423 - "tsx": "^4.8.1", 2424 - "yaml": "^2.4.2" 2425 - }, 2426 - "peerDependenciesMeta": { 2427 - "@types/node": { 2428 - "optional": true 2429 - }, 2430 - "jiti": { 2431 - "optional": true 2432 - }, 2433 - "less": { 2434 - "optional": true 2435 - }, 2436 - "lightningcss": { 2437 - "optional": true 2438 - }, 2439 - "sass": { 2440 - "optional": true 2441 - }, 2442 - "sass-embedded": { 2443 - "optional": true 2444 - }, 2445 - "stylus": { 2446 - "optional": true 2447 - }, 2448 - "sugarss": { 2449 - "optional": true 2450 - }, 2451 - "terser": { 2452 - "optional": true 2453 - }, 2454 - "tsx": { 2455 - "optional": true 2456 - }, 2457 - "yaml": { 2458 - "optional": true 2459 - } 2460 - } 2461 - }, 2462 - "node_modules/vite-node": { 2463 - "version": "3.0.9", 2464 - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.9.tgz", 2465 - "integrity": "sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==", 2466 - "dev": true, 2467 - "license": "MIT", 2468 - "dependencies": { 2469 - "cac": "^6.7.14", 2470 - "debug": "^4.4.0", 2471 - "es-module-lexer": "^1.6.0", 2472 - "pathe": "^2.0.3", 2473 - "vite": "^5.0.0 || ^6.0.0" 2474 - }, 2475 - "bin": { 2476 - "vite-node": "vite-node.mjs" 2477 - }, 2478 - "engines": { 2479 - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2480 - }, 2481 - "funding": { 2482 - "url": "https://opencollective.com/vitest" 2483 - } 2484 - }, 2485 - "node_modules/vitest": { 2486 - "version": "3.0.9", 2487 - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.9.tgz", 2488 - "integrity": "sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==", 2489 - "dev": true, 2490 - "license": "MIT", 2491 - "dependencies": { 2492 - "@vitest/expect": "3.0.9", 2493 - "@vitest/mocker": "3.0.9", 2494 - "@vitest/pretty-format": "^3.0.9", 2495 - "@vitest/runner": "3.0.9", 2496 - "@vitest/snapshot": "3.0.9", 2497 - "@vitest/spy": "3.0.9", 2498 - "@vitest/utils": "3.0.9", 2499 - "chai": "^5.2.0", 2500 - "debug": "^4.4.0", 2501 - "expect-type": "^1.1.0", 2502 - "magic-string": "^0.30.17", 2503 - "pathe": "^2.0.3", 2504 - "std-env": "^3.8.0", 2505 - "tinybench": "^2.9.0", 2506 - "tinyexec": "^0.3.2", 2507 - "tinypool": "^1.0.2", 2508 - "tinyrainbow": "^2.0.0", 2509 - "vite": "^5.0.0 || ^6.0.0", 2510 - "vite-node": "3.0.9", 2511 - "why-is-node-running": "^2.3.0" 2512 - }, 2513 - "bin": { 2514 - "vitest": "vitest.mjs" 2515 - }, 2516 - "engines": { 2517 - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2518 - }, 2519 - "funding": { 2520 - "url": "https://opencollective.com/vitest" 2521 - }, 2522 - "peerDependencies": { 2523 - "@edge-runtime/vm": "*", 2524 - "@types/debug": "^4.1.12", 2525 - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2526 - "@vitest/browser": "3.0.9", 2527 - "@vitest/ui": "3.0.9", 2528 - "happy-dom": "*", 2529 - "jsdom": "*" 2530 - }, 2531 - "peerDependenciesMeta": { 2532 - "@edge-runtime/vm": { 2533 - "optional": true 2534 - }, 2535 - "@types/debug": { 2536 - "optional": true 2537 - }, 2538 - "@types/node": { 2539 - "optional": true 2540 - }, 2541 - "@vitest/browser": { 2542 - "optional": true 2543 - }, 2544 - "@vitest/ui": { 2545 - "optional": true 2546 - }, 2547 - "happy-dom": { 2548 - "optional": true 2549 - }, 2550 - "jsdom": { 2551 - "optional": true 2552 - } 2553 - } 2554 - }, 2555 - "node_modules/why-is-node-running": { 2556 - "version": "2.3.0", 2557 - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", 2558 - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", 2559 - "dev": true, 2560 - "license": "MIT", 2561 - "dependencies": { 2562 - "siginfo": "^2.0.0", 2563 - "stackback": "0.0.2" 2564 - }, 2565 - "bin": { 2566 - "why-is-node-running": "cli.js" 2567 - }, 2568 - "engines": { 2569 - "node": ">=8" 2570 - } 2571 - }, 2572 - "node_modules/workerd": { 2573 - "version": "1.20250428.0", 2574 - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250428.0.tgz", 2575 - "integrity": "sha512-JJNWkHkwPQKQdvtM9UORijgYdcdJsihA4SfYjwh02IUQsdMyZ9jizV1sX9yWi9B9ptlohTW8UNHJEATuphGgdg==", 2576 - "dev": true, 2577 - "hasInstallScript": true, 2578 - "license": "Apache-2.0", 2579 - "bin": { 2580 - "workerd": "bin/workerd" 2581 - }, 2582 - "engines": { 2583 - "node": ">=16" 2584 - }, 2585 - "optionalDependencies": { 2586 - "@cloudflare/workerd-darwin-64": "1.20250428.0", 2587 - "@cloudflare/workerd-darwin-arm64": "1.20250428.0", 2588 - "@cloudflare/workerd-linux-64": "1.20250428.0", 2589 - "@cloudflare/workerd-linux-arm64": "1.20250428.0", 2590 - "@cloudflare/workerd-windows-64": "1.20250428.0" 2591 - } 2592 - }, 2593 - "node_modules/wrangler": { 2594 - "version": "4.14.1", 2595 - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.14.1.tgz", 2596 - "integrity": "sha512-EU7IThP7i68TBftJJSveogvWZ5k/WRijcJh3UclDWiWWhDZTPbL6LOJEFhHKqFzHOaC4Y2Aewt48rfTz0e7oCw==", 2597 - "dev": true, 2598 - "license": "MIT OR Apache-2.0", 2599 - "dependencies": { 2600 - "@cloudflare/kv-asset-handler": "0.4.0", 2601 - "@cloudflare/unenv-preset": "2.3.1", 2602 - "blake3-wasm": "2.1.5", 2603 - "esbuild": "0.25.2", 2604 - "miniflare": "4.20250428.1", 2605 - "path-to-regexp": "6.3.0", 2606 - "unenv": "2.0.0-rc.15", 2607 - "workerd": "1.20250428.0" 2608 - }, 2609 - "bin": { 2610 - "wrangler": "bin/wrangler.js", 2611 - "wrangler2": "bin/wrangler.js" 2612 - }, 2613 - "engines": { 2614 - "node": ">=18.0.0" 2615 - }, 2616 - "optionalDependencies": { 2617 - "fsevents": "~2.3.2", 2618 - "sharp": "^0.33.5" 2619 - }, 2620 - "peerDependencies": { 2621 - "@cloudflare/workers-types": "^4.20250428.0" 2622 - }, 2623 - "peerDependenciesMeta": { 2624 - "@cloudflare/workers-types": { 2625 - "optional": true 2626 - } 2627 - } 2628 - }, 2629 - "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": { 2630 - "version": "0.25.2", 2631 - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", 2632 - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", 2633 - "cpu": [ 2634 - "ppc64" 2635 - ], 2636 - "dev": true, 2637 - "license": "MIT", 2638 - "optional": true, 2639 - "os": [ 2640 - "aix" 2641 - ], 2642 - "engines": { 2643 - "node": ">=18" 2644 - } 2645 - }, 2646 - "node_modules/wrangler/node_modules/@esbuild/android-arm": { 2647 - "version": "0.25.2", 2648 - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", 2649 - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", 2650 - "cpu": [ 2651 - "arm" 2652 - ], 2653 - "dev": true, 2654 - "license": "MIT", 2655 - "optional": true, 2656 - "os": [ 2657 - "android" 2658 - ], 2659 - "engines": { 2660 - "node": ">=18" 2661 - } 2662 - }, 2663 - "node_modules/wrangler/node_modules/@esbuild/android-arm64": { 2664 - "version": "0.25.2", 2665 - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", 2666 - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", 2667 - "cpu": [ 2668 - "arm64" 2669 - ], 2670 - "dev": true, 2671 - "license": "MIT", 2672 - "optional": true, 2673 - "os": [ 2674 - "android" 2675 - ], 2676 - "engines": { 2677 - "node": ">=18" 2678 - } 2679 - }, 2680 - "node_modules/wrangler/node_modules/@esbuild/android-x64": { 2681 - "version": "0.25.2", 2682 - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", 2683 - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", 2684 - "cpu": [ 2685 - "x64" 2686 - ], 2687 - "dev": true, 2688 - "license": "MIT", 2689 - "optional": true, 2690 - "os": [ 2691 - "android" 2692 - ], 2693 - "engines": { 2694 - "node": ">=18" 2695 - } 2696 - }, 2697 - "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { 2698 - "version": "0.25.2", 2699 - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", 2700 - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", 2701 - "cpu": [ 2702 - "arm64" 2703 - ], 2704 - "dev": true, 2705 - "license": "MIT", 2706 - "optional": true, 2707 - "os": [ 2708 - "darwin" 2709 - ], 2710 - "engines": { 2711 - "node": ">=18" 2712 - } 2713 - }, 2714 - "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { 2715 - "version": "0.25.2", 2716 - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", 2717 - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", 2718 - "cpu": [ 2719 - "x64" 2720 - ], 2721 - "dev": true, 2722 - "license": "MIT", 2723 - "optional": true, 2724 - "os": [ 2725 - "darwin" 2726 - ], 2727 - "engines": { 2728 - "node": ">=18" 2729 - } 2730 - }, 2731 - "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { 2732 - "version": "0.25.2", 2733 - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", 2734 - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", 2735 - "cpu": [ 2736 - "arm64" 2737 - ], 2738 - "dev": true, 2739 - "license": "MIT", 2740 - "optional": true, 2741 - "os": [ 2742 - "freebsd" 2743 - ], 2744 - "engines": { 2745 - "node": ">=18" 2746 - } 2747 - }, 2748 - "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { 2749 - "version": "0.25.2", 2750 - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", 2751 - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", 2752 - "cpu": [ 2753 - "x64" 2754 - ], 2755 - "dev": true, 2756 - "license": "MIT", 2757 - "optional": true, 2758 - "os": [ 2759 - "freebsd" 2760 - ], 2761 - "engines": { 2762 - "node": ">=18" 2763 - } 2764 - }, 2765 - "node_modules/wrangler/node_modules/@esbuild/linux-arm": { 2766 - "version": "0.25.2", 2767 - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", 2768 - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", 2769 - "cpu": [ 2770 - "arm" 2771 - ], 2772 - "dev": true, 2773 - "license": "MIT", 2774 - "optional": true, 2775 - "os": [ 2776 - "linux" 2777 - ], 2778 - "engines": { 2779 - "node": ">=18" 2780 - } 2781 - }, 2782 - "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { 2783 - "version": "0.25.2", 2784 - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", 2785 - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", 2786 - "cpu": [ 2787 - "arm64" 2788 - ], 2789 - "dev": true, 2790 - "license": "MIT", 2791 - "optional": true, 2792 - "os": [ 2793 - "linux" 2794 - ], 2795 - "engines": { 2796 - "node": ">=18" 2797 - } 2798 - }, 2799 - "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { 2800 - "version": "0.25.2", 2801 - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", 2802 - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", 2803 - "cpu": [ 2804 - "ia32" 2805 - ], 2806 - "dev": true, 2807 - "license": "MIT", 2808 - "optional": true, 2809 - "os": [ 2810 - "linux" 2811 - ], 2812 - "engines": { 2813 - "node": ">=18" 2814 - } 2815 - }, 2816 - "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { 2817 - "version": "0.25.2", 2818 - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", 2819 - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", 2820 - "cpu": [ 2821 - "loong64" 2822 - ], 2823 - "dev": true, 2824 - "license": "MIT", 2825 - "optional": true, 2826 - "os": [ 2827 - "linux" 2828 - ], 2829 - "engines": { 2830 - "node": ">=18" 2831 - } 2832 - }, 2833 - "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { 2834 - "version": "0.25.2", 2835 - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", 2836 - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", 2837 - "cpu": [ 2838 - "mips64el" 2839 - ], 2840 - "dev": true, 2841 - "license": "MIT", 2842 - "optional": true, 2843 - "os": [ 2844 - "linux" 2845 - ], 2846 - "engines": { 2847 - "node": ">=18" 2848 - } 2849 - }, 2850 - "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { 2851 - "version": "0.25.2", 2852 - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", 2853 - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", 2854 - "cpu": [ 2855 - "ppc64" 2856 - ], 2857 - "dev": true, 2858 - "license": "MIT", 2859 - "optional": true, 2860 - "os": [ 2861 - "linux" 2862 - ], 2863 - "engines": { 2864 - "node": ">=18" 2865 - } 2866 - }, 2867 - "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { 2868 - "version": "0.25.2", 2869 - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", 2870 - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", 2871 - "cpu": [ 2872 - "riscv64" 2873 - ], 2874 - "dev": true, 2875 - "license": "MIT", 2876 - "optional": true, 2877 - "os": [ 2878 - "linux" 2879 - ], 2880 - "engines": { 2881 - "node": ">=18" 2882 - } 2883 - }, 2884 - "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { 2885 - "version": "0.25.2", 2886 - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", 2887 - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", 2888 - "cpu": [ 2889 - "s390x" 2890 - ], 2891 - "dev": true, 2892 - "license": "MIT", 2893 - "optional": true, 2894 - "os": [ 2895 - "linux" 2896 - ], 2897 - "engines": { 2898 - "node": ">=18" 2899 - } 2900 - }, 2901 - "node_modules/wrangler/node_modules/@esbuild/linux-x64": { 2902 - "version": "0.25.2", 2903 - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", 2904 - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", 2905 - "cpu": [ 2906 - "x64" 2907 - ], 2908 - "dev": true, 2909 - "license": "MIT", 2910 - "optional": true, 2911 - "os": [ 2912 - "linux" 2913 - ], 2914 - "engines": { 2915 - "node": ">=18" 2916 - } 2917 - }, 2918 - "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": { 2919 - "version": "0.25.2", 2920 - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", 2921 - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", 2922 - "cpu": [ 2923 - "arm64" 2924 - ], 2925 - "dev": true, 2926 - "license": "MIT", 2927 - "optional": true, 2928 - "os": [ 2929 - "netbsd" 2930 - ], 2931 - "engines": { 2932 - "node": ">=18" 2933 - } 2934 - }, 2935 - "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { 2936 - "version": "0.25.2", 2937 - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", 2938 - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", 2939 - "cpu": [ 2940 - "x64" 2941 - ], 2942 - "dev": true, 2943 - "license": "MIT", 2944 - "optional": true, 2945 - "os": [ 2946 - "netbsd" 2947 - ], 2948 - "engines": { 2949 - "node": ">=18" 2950 - } 2951 - }, 2952 - "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": { 2953 - "version": "0.25.2", 2954 - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", 2955 - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", 2956 - "cpu": [ 2957 - "arm64" 2958 - ], 2959 - "dev": true, 2960 - "license": "MIT", 2961 - "optional": true, 2962 - "os": [ 2963 - "openbsd" 2964 - ], 2965 - "engines": { 2966 - "node": ">=18" 2967 - } 2968 - }, 2969 - "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { 2970 - "version": "0.25.2", 2971 - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", 2972 - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", 2973 - "cpu": [ 2974 - "x64" 2975 - ], 2976 - "dev": true, 2977 - "license": "MIT", 2978 - "optional": true, 2979 - "os": [ 2980 - "openbsd" 2981 - ], 2982 - "engines": { 2983 - "node": ">=18" 2984 - } 2985 - }, 2986 - "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { 2987 - "version": "0.25.2", 2988 - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", 2989 - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", 2990 - "cpu": [ 2991 - "x64" 2992 - ], 2993 - "dev": true, 2994 - "license": "MIT", 2995 - "optional": true, 2996 - "os": [ 2997 - "sunos" 2998 - ], 2999 - "engines": { 3000 - "node": ">=18" 3001 - } 3002 - }, 3003 - "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { 3004 - "version": "0.25.2", 3005 - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", 3006 - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", 3007 - "cpu": [ 3008 - "arm64" 3009 - ], 3010 - "dev": true, 3011 - "license": "MIT", 3012 - "optional": true, 3013 - "os": [ 3014 - "win32" 3015 - ], 3016 - "engines": { 3017 - "node": ">=18" 3018 - } 3019 - }, 3020 - "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { 3021 - "version": "0.25.2", 3022 - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", 3023 - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", 3024 - "cpu": [ 3025 - "ia32" 3026 - ], 3027 - "dev": true, 3028 - "license": "MIT", 3029 - "optional": true, 3030 - "os": [ 3031 - "win32" 3032 - ], 3033 - "engines": { 3034 - "node": ">=18" 3035 - } 3036 - }, 3037 - "node_modules/wrangler/node_modules/@esbuild/win32-x64": { 3038 - "version": "0.25.2", 3039 - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", 3040 - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", 3041 - "cpu": [ 3042 - "x64" 3043 - ], 3044 - "dev": true, 3045 - "license": "MIT", 3046 - "optional": true, 3047 - "os": [ 3048 - "win32" 3049 - ], 3050 - "engines": { 3051 - "node": ">=18" 3052 - } 3053 - }, 3054 - "node_modules/wrangler/node_modules/esbuild": { 3055 - "version": "0.25.2", 3056 - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", 3057 - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", 3058 - "dev": true, 3059 - "hasInstallScript": true, 3060 - "license": "MIT", 3061 - "bin": { 3062 - "esbuild": "bin/esbuild" 3063 - }, 3064 - "engines": { 3065 - "node": ">=18" 3066 - }, 3067 - "optionalDependencies": { 3068 - "@esbuild/aix-ppc64": "0.25.2", 3069 - "@esbuild/android-arm": "0.25.2", 3070 - "@esbuild/android-arm64": "0.25.2", 3071 - "@esbuild/android-x64": "0.25.2", 3072 - "@esbuild/darwin-arm64": "0.25.2", 3073 - "@esbuild/darwin-x64": "0.25.2", 3074 - "@esbuild/freebsd-arm64": "0.25.2", 3075 - "@esbuild/freebsd-x64": "0.25.2", 3076 - "@esbuild/linux-arm": "0.25.2", 3077 - "@esbuild/linux-arm64": "0.25.2", 3078 - "@esbuild/linux-ia32": "0.25.2", 3079 - "@esbuild/linux-loong64": "0.25.2", 3080 - "@esbuild/linux-mips64el": "0.25.2", 3081 - "@esbuild/linux-ppc64": "0.25.2", 3082 - "@esbuild/linux-riscv64": "0.25.2", 3083 - "@esbuild/linux-s390x": "0.25.2", 3084 - "@esbuild/linux-x64": "0.25.2", 3085 - "@esbuild/netbsd-arm64": "0.25.2", 3086 - "@esbuild/netbsd-x64": "0.25.2", 3087 - "@esbuild/openbsd-arm64": "0.25.2", 3088 - "@esbuild/openbsd-x64": "0.25.2", 3089 - "@esbuild/sunos-x64": "0.25.2", 3090 - "@esbuild/win32-arm64": "0.25.2", 3091 - "@esbuild/win32-ia32": "0.25.2", 3092 - "@esbuild/win32-x64": "0.25.2" 3093 - } 3094 - }, 3095 - "node_modules/ws": { 3096 - "version": "8.18.0", 3097 - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", 3098 - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", 3099 - "dev": true, 3100 - "license": "MIT", 3101 - "engines": { 3102 - "node": ">=10.0.0" 3103 - }, 3104 - "peerDependencies": { 3105 - "bufferutil": "^4.0.1", 3106 - "utf-8-validate": ">=5.0.2" 3107 - }, 3108 - "peerDependenciesMeta": { 3109 - "bufferutil": { 3110 - "optional": true 3111 - }, 3112 - "utf-8-validate": { 3113 - "optional": true 3114 - } 3115 - } 3116 - }, 3117 - "node_modules/youch": { 3118 - "version": "3.3.4", 3119 - "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.4.tgz", 3120 - "integrity": "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==", 3121 - "dev": true, 3122 - "license": "MIT", 3123 - "dependencies": { 3124 - "cookie": "^0.7.1", 3125 - "mustache": "^4.2.0", 3126 - "stacktracey": "^2.1.8" 3127 - } 3128 - }, 3129 - "node_modules/zod": { 3130 - "version": "3.24.3", 3131 - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz", 3132 - "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==", 3133 - "license": "MIT", 3134 - "funding": { 3135 - "url": "https://github.com/sponsors/colinhacks" 3136 - } 3137 - } 3138 - } 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 + } 3139 3024 }
+14 -17
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 - "dependencies": { 12 - "@atproto/identity": "^0.4.1" 13 - }, 14 - "devDependencies": { 15 - "@cloudflare/vitest-pool-workers": "^0.8.19", 16 - "vitest": "~3.0.7", 17 - "wrangler": "^4.14.1" 18 - } 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 + } 19 16 }
+9 -121
avatar/src/index.js
··· 1 - import { IdResolver } from "@atproto/identity"; 2 - 3 1 export default { 4 2 async fetch(request, env) { 5 3 // Helper function to generate a color from a string ··· 16 14 return color; 17 15 }; 18 16 19 - // Helper function to fetch Tangled profile from PDS 20 - const getTangledAvatarFromPDS = async (actor, resolver) => { 21 - try { 22 - // Resolve the identity 23 - const identity = await resolver.resolve(actor); 24 - if (!identity) { 25 - console.log({ 26 - level: "debug", 27 - message: "failed to resolve identity", 28 - actor: actor, 29 - }); 30 - return null; 31 - } 32 - 33 - const did = identity.did; 34 - const pdsEndpoint = identity.pdsUrl; 35 - 36 - if (!pdsEndpoint) { 37 - console.log({ 38 - level: "debug", 39 - message: "no PDS endpoint found", 40 - actor: actor, 41 - did: did, 42 - }); 43 - return null; 44 - } 45 - 46 - console.log({ 47 - level: "debug", 48 - message: "fetching Tangled profile from PDS", 49 - actor: actor, 50 - did: did, 51 - pdsEndpoint: pdsEndpoint, 52 - }); 53 - 54 - // Fetch the Tangled profile record from PDS 55 - const profileResponse = await fetch( 56 - `${pdsEndpoint}/xrpc/com.atproto.repo.getRecord?repo=${did}&collection=org.tangled.actor.profile&rkey=self`, 57 - ); 58 - 59 - if (!profileResponse.ok) { 60 - console.log({ 61 - level: "debug", 62 - message: "no Tangled profile found on PDS", 63 - actor: actor, 64 - status: profileResponse.status, 65 - }); 66 - return null; 67 - } 68 - 69 - const profileData = await profileResponse.json(); 70 - const avatarCID = profileData?.value?.avatar; 71 - 72 - if (!avatarCID) { 73 - console.log({ 74 - level: "debug", 75 - message: "Tangled profile has no avatar CID", 76 - actor: actor, 77 - }); 78 - return null; 79 - } 80 - 81 - // Construct blob URL 82 - const blobUrl = `${pdsEndpoint}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${avatarCID}`; 83 - 84 - console.log({ 85 - level: "debug", 86 - message: "found Tangled avatar", 87 - actor: actor, 88 - avatarCID: avatarCID, 89 - }); 90 - 91 - return blobUrl; 92 - } catch (e) { 93 - console.log({ 94 - level: "warn", 95 - message: "error fetching Tangled avatar from PDS", 96 - actor: actor, 97 - error: e.message, 98 - }); 99 - return null; 100 - } 101 - }; 102 - 103 17 const url = new URL(request.url); 104 18 const { pathname, searchParams } = url; 105 19 106 20 if (!pathname || pathname === "/") { 107 - return new Response( 108 - `This is Tangled's avatar service. It fetches your pretty avatar from your PDS, Bluesky, or generates a placeholder. 109 - You can't use this directly unfortunately since all requests are signed and may only originate from the appview.`, 110 - ); 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.`); 111 23 } 112 24 113 25 const size = searchParams.get("size"); ··· 156 68 } 157 69 158 70 try { 159 - let avatarUrl = null; 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; 160 76 161 - // Create identity resolver 162 - const resolver = new IdResolver(); 163 - 164 - // Try to get Tangled avatar from user's PDS first 165 - avatarUrl = await getTangledAvatarFromPDS(actor, resolver); 166 - 167 - // If no Tangled avatar, fall back to Bluesky 168 - if (!avatarUrl) { 169 - console.log({ 170 - level: "debug", 171 - message: "no Tangled avatar, falling back to Bluesky", 172 - actor: actor, 173 - }); 174 - 175 - const profileResponse = await fetch( 176 - `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${actor}`, 177 - ); 178 - 179 - if (profileResponse.ok) { 180 - const profile = await profileResponse.json(); 181 - avatarUrl = profile.avatar; 182 - } 183 - } 77 + let avatarUrl = profile.avatar; 184 78 185 79 if (!avatarUrl) { 186 80 // Generate a random color based on the actor string 187 - console.log({ 188 - level: "debug", 189 - message: "no avatar found, generating placeholder", 190 - actor: actor, 191 - }); 192 - 193 81 const bgColor = stringToColor(actor); 194 82 const size = resizeToTiny ? 32 : 128; 195 83 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>`; ··· 205 93 return response; 206 94 } 207 95 208 - // Fetch and optionally resize the avatar 96 + // Resize if requested 209 97 let avatarResponse; 210 98 if (resizeToTiny) { 211 99 avatarResponse = await fetch(avatarUrl, {
+9 -9
flake.lock
··· 35 35 "systems": "systems" 36 36 }, 37 37 "locked": { 38 - "lastModified": 1694529238, 39 - "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", 38 + "lastModified": 1731533236, 39 + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 40 40 "owner": "numtide", 41 41 "repo": "flake-utils", 42 - "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", 42 + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 43 43 "type": "github" 44 44 }, 45 45 "original": { ··· 56 56 ] 57 57 }, 58 58 "locked": { 59 - "lastModified": 1754078208, 60 - "narHash": "sha256-YVoIFDCDpYuU3riaDEJ3xiGdPOtsx4sR5eTzHTytPV8=", 59 + "lastModified": 1763982521, 60 + "narHash": "sha256-ur4QIAHwgFc0vXiaxn5No/FuZicxBr2p0gmT54xZkUQ=", 61 61 "owner": "nix-community", 62 62 "repo": "gomod2nix", 63 - "rev": "7f963246a71626c7fc70b431a315c4388a0c95cf", 63 + "rev": "02e63a239d6eabd595db56852535992c898eba72", 64 64 "type": "github" 65 65 }, 66 66 "original": { ··· 150 150 }, 151 151 "nixpkgs": { 152 152 "locked": { 153 - "lastModified": 1751984180, 154 - "narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=", 153 + "lastModified": 1766070988, 154 + "narHash": "sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc=", 155 155 "owner": "nixos", 156 156 "repo": "nixpkgs", 157 - "rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0", 157 + "rev": "c6245e83d836d0433170a16eb185cefe0572f8b8", 158 158 "type": "github" 159 159 }, 160 160 "original": {
-2
flake.nix
··· 80 80 }).buildGoApplication; 81 81 modules = ./nix/gomod2nix.toml; 82 82 sqlite-lib = self.callPackage ./nix/pkgs/sqlite-lib.nix { 83 - inherit (pkgs) gcc; 84 83 inherit sqlite-lib-src; 85 84 }; 86 85 lexgen = self.callPackage ./nix/pkgs/lexgen.nix {inherit indigo;}; ··· 156 155 nativeBuildInputs = [ 157 156 pkgs.go 158 157 pkgs.air 159 - pkgs.tilt 160 158 pkgs.gopls 161 159 pkgs.httpie 162 160 pkgs.litecli
+3 -2
go.mod
··· 1 1 module tangled.org/core 2 2 3 - go 1.24.4 3 + go 1.25.0 4 4 5 5 require ( 6 6 github.com/Blank-Xu/sql-adapter v1.1.1 ··· 45 45 github.com/urfave/cli/v3 v3.3.3 46 46 github.com/whyrusleeping/cbor-gen v0.3.1 47 47 github.com/yuin/goldmark v1.7.13 48 + github.com/yuin/goldmark-emoji v1.0.6 48 49 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc 49 50 gitlab.com/staticnoise/goldmark-callout v0.0.0-20240609120641-6366b799e4ab 50 51 golang.org/x/crypto v0.40.0 51 52 golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b 52 53 golang.org/x/image v0.31.0 53 54 golang.org/x/net v0.42.0 54 - golang.org/x/sync v0.17.0 55 55 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da 56 56 gopkg.in/yaml.v3 v3.0.1 57 57 ) ··· 203 203 go.uber.org/atomic v1.11.0 // indirect 204 204 go.uber.org/multierr v1.11.0 // indirect 205 205 go.uber.org/zap v1.27.0 // indirect 206 + golang.org/x/sync v0.17.0 // indirect 206 207 golang.org/x/sys v0.34.0 // indirect 207 208 golang.org/x/text v0.29.0 // indirect 208 209 golang.org/x/time v0.12.0 // indirect
+2
go.sum
··· 505 505 github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 506 506 github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA= 507 507 github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= 508 + github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs= 509 + github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA= 508 510 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= 509 511 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= 510 512 gitlab.com/staticnoise/goldmark-callout v0.0.0-20240609120641-6366b799e4ab h1:gK9tS6QJw5F0SIhYJnGG2P83kuabOdmWBbSmZhJkz2A=
+4 -4
hook/hook.go
··· 48 48 }, 49 49 Commands: []*cli.Command{ 50 50 { 51 - Name: "post-recieve", 52 - Usage: "sends a post-recieve hook to the knot (waits for stdin)", 53 - Action: postRecieve, 51 + Name: "post-receive", 52 + Usage: "sends a post-receive hook to the knot (waits for stdin)", 53 + Action: postReceive, 54 54 }, 55 55 }, 56 56 } 57 57 } 58 58 59 - func postRecieve(ctx context.Context, cmd *cli.Command) error { 59 + func postReceive(ctx context.Context, cmd *cli.Command) error { 60 60 gitDir := cmd.String("git-dir") 61 61 userDid := cmd.String("user-did") 62 62 userHandle := cmd.String("user-handle")
+1 -1
hook/setup.go
··· 138 138 option_var="GIT_PUSH_OPTION_$i" 139 139 push_options+=(-push-option "${!option_var}") 140 140 done 141 - %s hook -git-dir "$GIT_DIR" -user-did "$GIT_USER_DID" -user-handle "$GIT_USER_HANDLE" -internal-api "%s" "${push_options[@]}" post-recieve 141 + %s hook -git-dir "$GIT_DIR" -user-did "$GIT_USER_DID" -user-handle "$GIT_USER_HANDLE" -internal-api "%s" "${push_options[@]}" post-receive 142 142 `, executablePath, config.internalApi) 143 143 144 144 return os.WriteFile(hookPath, []byte(hookContent), 0755)
+19
input.css
··· 89 89 @apply no-underline text-black hover:underline hover:text-gray-800 dark:text-white dark:hover:text-gray-300; 90 90 } 91 91 92 + #navigation-menu-popover li:not(:last-of-type) a { 93 + @apply flex gap-2 items-center px-2 pb-2 pt-1.5 rounded-sm hover:bg-green-50 hover:text-green-700 no-underline dark:hover:text-green-50 dark:hover:bg-green-700; 94 + } 95 + 96 + a[hx-post="/logout"] { 97 + @apply no-underline; 98 + } 99 + 92 100 label { 93 101 @apply block text-gray-900 text-sm font-bold py-2 uppercase dark:text-gray-100; 94 102 } ··· 962 970 color: #f9fafb; 963 971 } 964 972 } 973 + 974 + .site-navigation-dropdown-trigger { 975 + anchor-name: --dropdown-trigger; 976 + } 977 + 978 + .site-navigation-popover { 979 + margin: 0; 980 + inset: auto; 981 + position-anchor: --dropdown-trigger; 982 + position-area: bottom left; 983 + }
+81
knotserver/db/db.go
··· 1 + package db 2 + 3 + import ( 4 + "context" 5 + "database/sql" 6 + "log/slog" 7 + "strings" 8 + 9 + _ "github.com/mattn/go-sqlite3" 10 + "tangled.org/core/log" 11 + ) 12 + 13 + type DB struct { 14 + db *sql.DB 15 + logger *slog.Logger 16 + } 17 + 18 + func Setup(ctx context.Context, dbPath string) (*DB, error) { 19 + // https://github.com/mattn/go-sqlite3#connection-string 20 + opts := []string{ 21 + "_foreign_keys=1", 22 + "_journal_mode=WAL", 23 + "_synchronous=NORMAL", 24 + "_auto_vacuum=incremental", 25 + } 26 + 27 + logger := log.FromContext(ctx) 28 + logger = log.SubLogger(logger, "db") 29 + 30 + db, err := sql.Open("sqlite3", dbPath+"?"+strings.Join(opts, "&")) 31 + if err != nil { 32 + return nil, err 33 + } 34 + 35 + conn, err := db.Conn(ctx) 36 + if err != nil { 37 + return nil, err 38 + } 39 + defer conn.Close() 40 + 41 + _, err = conn.ExecContext(ctx, ` 42 + create table if not exists known_dids ( 43 + did text primary key 44 + ); 45 + 46 + create table if not exists public_keys ( 47 + id integer primary key autoincrement, 48 + did text not null, 49 + key text not null, 50 + created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), 51 + unique(did, key), 52 + foreign key (did) references known_dids(did) on delete cascade 53 + ); 54 + 55 + create table if not exists _jetstream ( 56 + id integer primary key autoincrement, 57 + last_time_us integer not null 58 + ); 59 + 60 + create table if not exists events ( 61 + rkey text not null, 62 + nsid text not null, 63 + event text not null, -- json 64 + created integer not null default (strftime('%s', 'now')), 65 + primary key (rkey, nsid) 66 + ); 67 + 68 + create table if not exists migrations ( 69 + id integer primary key autoincrement, 70 + name text unique 71 + ); 72 + `) 73 + if err != nil { 74 + return nil, err 75 + } 76 + 77 + return &DB{ 78 + db: db, 79 + logger: logger, 80 + }, nil 81 + }
-64
knotserver/db/init.go
··· 1 - package db 2 - 3 - import ( 4 - "database/sql" 5 - "strings" 6 - 7 - _ "github.com/mattn/go-sqlite3" 8 - ) 9 - 10 - type DB struct { 11 - db *sql.DB 12 - } 13 - 14 - func Setup(dbPath string) (*DB, error) { 15 - // https://github.com/mattn/go-sqlite3#connection-string 16 - opts := []string{ 17 - "_foreign_keys=1", 18 - "_journal_mode=WAL", 19 - "_synchronous=NORMAL", 20 - "_auto_vacuum=incremental", 21 - } 22 - 23 - db, err := sql.Open("sqlite3", dbPath+"?"+strings.Join(opts, "&")) 24 - if err != nil { 25 - return nil, err 26 - } 27 - 28 - // NOTE: If any other migration is added here, you MUST 29 - // copy the pattern in appview: use a single sql.Conn 30 - // for every migration. 31 - 32 - _, err = db.Exec(` 33 - create table if not exists known_dids ( 34 - did text primary key 35 - ); 36 - 37 - create table if not exists public_keys ( 38 - id integer primary key autoincrement, 39 - did text not null, 40 - key text not null, 41 - created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), 42 - unique(did, key), 43 - foreign key (did) references known_dids(did) on delete cascade 44 - ); 45 - 46 - create table if not exists _jetstream ( 47 - id integer primary key autoincrement, 48 - last_time_us integer not null 49 - ); 50 - 51 - create table if not exists events ( 52 - rkey text not null, 53 - nsid text not null, 54 - event text not null, -- json 55 - created integer not null default (strftime('%s', 'now')), 56 - primary key (rkey, nsid) 57 - ); 58 - `) 59 - if err != nil { 60 - return nil, err 61 - } 62 - 63 - return &DB{db: db}, nil 64 - }
+13 -1
knotserver/git/service/service.go
··· 95 95 return c.RunService(cmd) 96 96 } 97 97 98 + func (c *ServiceCommand) UploadArchive() error { 99 + cmd := exec.Command("git", []string{ 100 + "upload-archive", 101 + ".", 102 + }...) 103 + 104 + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} 105 + cmd.Env = append(cmd.Env, fmt.Sprintf("GIT_PROTOCOL=%s", c.GitProtocol)) 106 + cmd.Dir = c.Dir 107 + 108 + return c.RunService(cmd) 109 + } 110 + 98 111 func (c *ServiceCommand) UploadPack() error { 99 112 cmd := exec.Command("git", []string{ 100 - "-c", "uploadpack.allowFilter=true", 101 113 "upload-pack", 102 114 "--stateless-rpc", 103 115 ".",
+47
knotserver/git.go
··· 56 56 } 57 57 } 58 58 59 + func (h *Knot) UploadArchive(w http.ResponseWriter, r *http.Request) { 60 + did := chi.URLParam(r, "did") 61 + name := chi.URLParam(r, "name") 62 + repo, err := securejoin.SecureJoin(h.c.Repo.ScanPath, filepath.Join(did, name)) 63 + if err != nil { 64 + gitError(w, err.Error(), http.StatusInternalServerError) 65 + h.l.Error("git: failed to secure join repo path", "handler", "UploadPack", "error", err) 66 + return 67 + } 68 + 69 + const expectedContentType = "application/x-git-upload-archive-request" 70 + contentType := r.Header.Get("Content-Type") 71 + if contentType != expectedContentType { 72 + gitError(w, fmt.Sprintf("Expected Content-Type: '%s', but received '%s'.", expectedContentType, contentType), http.StatusUnsupportedMediaType) 73 + } 74 + 75 + var bodyReader io.ReadCloser = r.Body 76 + if r.Header.Get("Content-Encoding") == "gzip" { 77 + gzipReader, err := gzip.NewReader(r.Body) 78 + if err != nil { 79 + gitError(w, err.Error(), http.StatusInternalServerError) 80 + h.l.Error("git: failed to create gzip reader", "handler", "UploadArchive", "error", err) 81 + return 82 + } 83 + defer gzipReader.Close() 84 + bodyReader = gzipReader 85 + } 86 + 87 + w.Header().Set("Content-Type", "application/x-git-upload-archive-result") 88 + 89 + h.l.Info("git: executing git-upload-archive", "handler", "UploadArchive", "repo", repo) 90 + 91 + cmd := service.ServiceCommand{ 92 + GitProtocol: r.Header.Get("Git-Protocol"), 93 + Dir: repo, 94 + Stdout: w, 95 + Stdin: bodyReader, 96 + } 97 + 98 + w.WriteHeader(http.StatusOK) 99 + 100 + if err := cmd.UploadArchive(); err != nil { 101 + h.l.Error("git: failed to execute git-upload-pack", "handler", "UploadPack", "error", err) 102 + return 103 + } 104 + } 105 + 59 106 func (h *Knot) UploadPack(w http.ResponseWriter, r *http.Request) { 60 107 did := chi.URLParam(r, "did") 61 108 name := chi.URLParam(r, "name")
+1
knotserver/router.go
··· 82 82 r.Route("/{name}", func(r chi.Router) { 83 83 // routes for git operations 84 84 r.Get("/info/refs", h.InfoRefs) 85 + r.Post("/git-upload-archive", h.UploadArchive) 85 86 r.Post("/git-upload-pack", h.UploadPack) 86 87 r.Post("/git-receive-pack", h.ReceivePack) 87 88 })
+1 -1
knotserver/server.go
··· 64 64 logger.Info("running in dev mode, signature verification is disabled") 65 65 } 66 66 67 - db, err := db.Setup(c.Server.DBPath) 67 + db, err := db.Setup(ctx, c.Server.DBPath) 68 68 if err != nil { 69 69 return fmt.Errorf("failed to load db: %w", err) 70 70 }
+3 -7
lexicons/actor/profile.json
··· 8 8 "key": "literal:self", 9 9 "record": { 10 10 "type": "object", 11 - "required": ["bluesky"], 11 + "required": [ 12 + "bluesky" 13 + ], 12 14 "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 - }, 19 15 "description": { 20 16 "type": "string", 21 17 "description": "Free-form profile description text.",
+3
nix/gomod2nix.toml
··· 530 530 [mod."github.com/yuin/goldmark"] 531 531 version = "v1.7.13" 532 532 hash = "sha256-vBCxZrPYPc8x/nvAAv3Au59dCCyfS80Vw3/a9EXK7TE=" 533 + [mod."github.com/yuin/goldmark-emoji"] 534 + version = "v1.0.6" 535 + hash = "sha256-+d6bZzOPE+JSFsZbQNZMCWE+n3jgcQnkPETVk47mxSY=" 533 536 [mod."github.com/yuin/goldmark-highlighting/v2"] 534 537 version = "v2.0.0-20230729083705-37449abec8cc" 535 538 hash = "sha256-HpiwU7jIeDUAg2zOpTIiviQir8dpRPuXYh2nqFFccpg="
+7 -5
nix/pkgs/sqlite-lib.nix
··· 1 1 { 2 - gcc, 3 2 stdenv, 4 3 sqlite-lib-src, 5 4 }: 6 5 stdenv.mkDerivation { 7 6 name = "sqlite-lib"; 8 7 src = sqlite-lib-src; 9 - nativeBuildInputs = [gcc]; 8 + 10 9 buildPhase = '' 11 - gcc -c sqlite3.c 12 - ar rcs libsqlite3.a sqlite3.o 13 - ranlib libsqlite3.a 10 + $CC -c sqlite3.c 11 + $AR rcs libsqlite3.a sqlite3.o 12 + $RANLIB libsqlite3.a 13 + ''; 14 + 15 + installPhase = '' 14 16 mkdir -p $out/include $out/lib 15 17 cp *.h $out/include 16 18 cp libsqlite3.a $out/lib
+31
sets/gen.go
··· 1 + package sets 2 + 3 + import ( 4 + "math/rand" 5 + "reflect" 6 + "testing/quick" 7 + ) 8 + 9 + func (_ Set[T]) Generate(rand *rand.Rand, size int) reflect.Value { 10 + s := New[T]() 11 + 12 + var zero T 13 + itemType := reflect.TypeOf(zero) 14 + 15 + for { 16 + if s.Len() >= size { 17 + break 18 + } 19 + 20 + item, ok := quick.Value(itemType, rand) 21 + if !ok { 22 + continue 23 + } 24 + 25 + if val, ok := item.Interface().(T); ok { 26 + s.Insert(val) 27 + } 28 + } 29 + 30 + return reflect.ValueOf(s) 31 + }
+35
sets/readme.txt
··· 1 + sets 2 + ---- 3 + set datastructure for go with generics and iterators. the 4 + api is supposed to mimic rust's std::collections::HashSet api. 5 + 6 + s1 := sets.Collect(slices.Values([]int{1, 2, 3, 4})) 7 + s2 := sets.Collect(slices.Values([]int{1, 2, 3, 4, 5, 6})) 8 + 9 + union := sets.Collect(s1.Union(s2)) 10 + intersect := sets.Collect(s1.Intersection(s2)) 11 + diff := sets.Collect(s1.Difference(s2)) 12 + symdiff := sets.Collect(s1.SymmetricDifference(s2)) 13 + 14 + s1.Len() // 4 15 + s1.Contains(1) // true 16 + s1.IsEmpty() // false 17 + s1.IsSubset(s2) // true 18 + s1.IsSuperset(s2) // false 19 + s1.IsDisjoint(s2) // false 20 + 21 + if exists := s1.Insert(1); exists { 22 + // already existed in set 23 + } 24 + 25 + if existed := s1.Remove(1); existed { 26 + // existed in set, now removed 27 + } 28 + 29 + 30 + testing 31 + ------- 32 + includes property-based tests using the wonderful 33 + testing/quick module! 34 + 35 + go test -v
+174
sets/set.go
··· 1 + package sets 2 + 3 + import ( 4 + "iter" 5 + "maps" 6 + ) 7 + 8 + type Set[T comparable] struct { 9 + data map[T]struct{} 10 + } 11 + 12 + func New[T comparable]() Set[T] { 13 + return Set[T]{ 14 + data: make(map[T]struct{}), 15 + } 16 + } 17 + 18 + func (s *Set[T]) Insert(item T) bool { 19 + _, exists := s.data[item] 20 + s.data[item] = struct{}{} 21 + return !exists 22 + } 23 + 24 + func Singleton[T comparable](item T) Set[T] { 25 + n := New[T]() 26 + _ = n.Insert(item) 27 + return n 28 + } 29 + 30 + func (s *Set[T]) Remove(item T) bool { 31 + _, exists := s.data[item] 32 + if exists { 33 + delete(s.data, item) 34 + } 35 + return exists 36 + } 37 + 38 + func (s Set[T]) Contains(item T) bool { 39 + _, exists := s.data[item] 40 + return exists 41 + } 42 + 43 + func (s Set[T]) Len() int { 44 + return len(s.data) 45 + } 46 + 47 + func (s Set[T]) IsEmpty() bool { 48 + return len(s.data) == 0 49 + } 50 + 51 + func (s *Set[T]) Clear() { 52 + s.data = make(map[T]struct{}) 53 + } 54 + 55 + func (s Set[T]) All() iter.Seq[T] { 56 + return func(yield func(T) bool) { 57 + for item := range s.data { 58 + if !yield(item) { 59 + return 60 + } 61 + } 62 + } 63 + } 64 + 65 + func (s Set[T]) Clone() Set[T] { 66 + return Set[T]{ 67 + data: maps.Clone(s.data), 68 + } 69 + } 70 + 71 + func (s Set[T]) Union(other Set[T]) iter.Seq[T] { 72 + if s.Len() >= other.Len() { 73 + return chain(s.All(), other.Difference(s)) 74 + } else { 75 + return chain(other.All(), s.Difference(other)) 76 + } 77 + } 78 + 79 + func chain[T any](seqs ...iter.Seq[T]) iter.Seq[T] { 80 + return func(yield func(T) bool) { 81 + for _, seq := range seqs { 82 + for item := range seq { 83 + if !yield(item) { 84 + return 85 + } 86 + } 87 + } 88 + } 89 + } 90 + 91 + func (s Set[T]) Intersection(other Set[T]) iter.Seq[T] { 92 + return func(yield func(T) bool) { 93 + for item := range s.data { 94 + if other.Contains(item) { 95 + if !yield(item) { 96 + return 97 + } 98 + } 99 + } 100 + } 101 + } 102 + 103 + func (s Set[T]) Difference(other Set[T]) iter.Seq[T] { 104 + return func(yield func(T) bool) { 105 + for item := range s.data { 106 + if !other.Contains(item) { 107 + if !yield(item) { 108 + return 109 + } 110 + } 111 + } 112 + } 113 + } 114 + 115 + func (s Set[T]) SymmetricDifference(other Set[T]) iter.Seq[T] { 116 + return func(yield func(T) bool) { 117 + for item := range s.data { 118 + if !other.Contains(item) { 119 + if !yield(item) { 120 + return 121 + } 122 + } 123 + } 124 + for item := range other.data { 125 + if !s.Contains(item) { 126 + if !yield(item) { 127 + return 128 + } 129 + } 130 + } 131 + } 132 + } 133 + 134 + func (s Set[T]) IsSubset(other Set[T]) bool { 135 + for item := range s.data { 136 + if !other.Contains(item) { 137 + return false 138 + } 139 + } 140 + return true 141 + } 142 + 143 + func (s Set[T]) IsSuperset(other Set[T]) bool { 144 + return other.IsSubset(s) 145 + } 146 + 147 + func (s Set[T]) IsDisjoint(other Set[T]) bool { 148 + for item := range s.data { 149 + if other.Contains(item) { 150 + return false 151 + } 152 + } 153 + return true 154 + } 155 + 156 + func (s Set[T]) Equal(other Set[T]) bool { 157 + if s.Len() != other.Len() { 158 + return false 159 + } 160 + for item := range s.data { 161 + if !other.Contains(item) { 162 + return false 163 + } 164 + } 165 + return true 166 + } 167 + 168 + func Collect[T comparable](seq iter.Seq[T]) Set[T] { 169 + result := New[T]() 170 + for item := range seq { 171 + result.Insert(item) 172 + } 173 + return result 174 + }
+411
sets/set_test.go
··· 1 + package sets 2 + 3 + import ( 4 + "slices" 5 + "testing" 6 + "testing/quick" 7 + ) 8 + 9 + func TestNew(t *testing.T) { 10 + s := New[int]() 11 + if s.Len() != 0 { 12 + t.Errorf("New set should be empty, got length %d", s.Len()) 13 + } 14 + if !s.IsEmpty() { 15 + t.Error("New set should be empty") 16 + } 17 + } 18 + 19 + func TestFromSlice(t *testing.T) { 20 + s := Collect(slices.Values([]int{1, 2, 3, 2, 1})) 21 + if s.Len() != 3 { 22 + t.Errorf("Expected length 3, got %d", s.Len()) 23 + } 24 + if !s.Contains(1) || !s.Contains(2) || !s.Contains(3) { 25 + t.Error("Set should contain all unique elements from slice") 26 + } 27 + } 28 + 29 + func TestInsert(t *testing.T) { 30 + s := New[string]() 31 + 32 + if !s.Insert("hello") { 33 + t.Error("First insert should return true") 34 + } 35 + if s.Insert("hello") { 36 + t.Error("Duplicate insert should return false") 37 + } 38 + if s.Len() != 1 { 39 + t.Errorf("Expected length 1, got %d", s.Len()) 40 + } 41 + } 42 + 43 + func TestRemove(t *testing.T) { 44 + s := Collect(slices.Values([]int{1, 2, 3})) 45 + 46 + if !s.Remove(2) { 47 + t.Error("Remove existing element should return true") 48 + } 49 + if s.Remove(2) { 50 + t.Error("Remove non-existing element should return false") 51 + } 52 + if s.Contains(2) { 53 + t.Error("Element should be removed") 54 + } 55 + if s.Len() != 2 { 56 + t.Errorf("Expected length 2, got %d", s.Len()) 57 + } 58 + } 59 + 60 + func TestContains(t *testing.T) { 61 + s := Collect(slices.Values([]int{1, 2, 3})) 62 + 63 + if !s.Contains(1) { 64 + t.Error("Should contain 1") 65 + } 66 + if s.Contains(4) { 67 + t.Error("Should not contain 4") 68 + } 69 + } 70 + 71 + func TestClear(t *testing.T) { 72 + s := Collect(slices.Values([]int{1, 2, 3})) 73 + s.Clear() 74 + 75 + if !s.IsEmpty() { 76 + t.Error("Set should be empty after clear") 77 + } 78 + if s.Len() != 0 { 79 + t.Errorf("Expected length 0, got %d", s.Len()) 80 + } 81 + } 82 + 83 + func TestIterator(t *testing.T) { 84 + s := Collect(slices.Values([]int{1, 2, 3})) 85 + var items []int 86 + 87 + for item := range s.All() { 88 + items = append(items, item) 89 + } 90 + 91 + slices.Sort(items) 92 + expected := []int{1, 2, 3} 93 + if !slices.Equal(items, expected) { 94 + t.Errorf("Expected %v, got %v", expected, items) 95 + } 96 + } 97 + 98 + func TestClone(t *testing.T) { 99 + s1 := Collect(slices.Values([]int{1, 2, 3})) 100 + s2 := s1.Clone() 101 + 102 + if !s1.Equal(s2) { 103 + t.Error("Cloned set should be equal to original") 104 + } 105 + 106 + s2.Insert(4) 107 + if s1.Contains(4) { 108 + t.Error("Modifying clone should not affect original") 109 + } 110 + } 111 + 112 + func TestUnion(t *testing.T) { 113 + s1 := Collect(slices.Values([]int{1, 2})) 114 + s2 := Collect(slices.Values([]int{2, 3})) 115 + 116 + result := Collect(s1.Union(s2)) 117 + expected := Collect(slices.Values([]int{1, 2, 3})) 118 + 119 + if !result.Equal(expected) { 120 + t.Errorf("Expected %v, got %v", expected, result) 121 + } 122 + } 123 + 124 + func TestIntersection(t *testing.T) { 125 + s1 := Collect(slices.Values([]int{1, 2, 3})) 126 + s2 := Collect(slices.Values([]int{2, 3, 4})) 127 + 128 + expected := Collect(slices.Values([]int{2, 3})) 129 + result := Collect(s1.Intersection(s2)) 130 + 131 + if !result.Equal(expected) { 132 + t.Errorf("Expected %v, got %v", expected, result) 133 + } 134 + } 135 + 136 + func TestDifference(t *testing.T) { 137 + s1 := Collect(slices.Values([]int{1, 2, 3})) 138 + s2 := Collect(slices.Values([]int{2, 3, 4})) 139 + 140 + expected := Collect(slices.Values([]int{1})) 141 + result := Collect(s1.Difference(s2)) 142 + 143 + if !result.Equal(expected) { 144 + t.Errorf("Expected %v, got %v", expected, result) 145 + } 146 + } 147 + 148 + func TestSymmetricDifference(t *testing.T) { 149 + s1 := Collect(slices.Values([]int{1, 2, 3})) 150 + s2 := Collect(slices.Values([]int{2, 3, 4})) 151 + 152 + expected := Collect(slices.Values([]int{1, 4})) 153 + result := Collect(s1.SymmetricDifference(s2)) 154 + 155 + if !result.Equal(expected) { 156 + t.Errorf("Expected %v, got %v", expected, result) 157 + } 158 + } 159 + 160 + func TestSymmetricDifferenceCommutativeProperty(t *testing.T) { 161 + s1 := Collect(slices.Values([]int{1, 2, 3})) 162 + s2 := Collect(slices.Values([]int{2, 3, 4})) 163 + 164 + result1 := Collect(s1.SymmetricDifference(s2)) 165 + result2 := Collect(s2.SymmetricDifference(s1)) 166 + 167 + if !result1.Equal(result2) { 168 + t.Errorf("Expected %v, got %v", result1, result2) 169 + } 170 + } 171 + 172 + func TestIsSubset(t *testing.T) { 173 + s1 := Collect(slices.Values([]int{1, 2})) 174 + s2 := Collect(slices.Values([]int{1, 2, 3})) 175 + 176 + if !s1.IsSubset(s2) { 177 + t.Error("s1 should be subset of s2") 178 + } 179 + if s2.IsSubset(s1) { 180 + t.Error("s2 should not be subset of s1") 181 + } 182 + } 183 + 184 + func TestIsSuperset(t *testing.T) { 185 + s1 := Collect(slices.Values([]int{1, 2, 3})) 186 + s2 := Collect(slices.Values([]int{1, 2})) 187 + 188 + if !s1.IsSuperset(s2) { 189 + t.Error("s1 should be superset of s2") 190 + } 191 + if s2.IsSuperset(s1) { 192 + t.Error("s2 should not be superset of s1") 193 + } 194 + } 195 + 196 + func TestIsDisjoint(t *testing.T) { 197 + s1 := Collect(slices.Values([]int{1, 2})) 198 + s2 := Collect(slices.Values([]int{3, 4})) 199 + s3 := Collect(slices.Values([]int{2, 3})) 200 + 201 + if !s1.IsDisjoint(s2) { 202 + t.Error("s1 and s2 should be disjoint") 203 + } 204 + if s1.IsDisjoint(s3) { 205 + t.Error("s1 and s3 should not be disjoint") 206 + } 207 + } 208 + 209 + func TestEqual(t *testing.T) { 210 + s1 := Collect(slices.Values([]int{1, 2, 3})) 211 + s2 := Collect(slices.Values([]int{3, 2, 1})) 212 + s3 := Collect(slices.Values([]int{1, 2})) 213 + 214 + if !s1.Equal(s2) { 215 + t.Error("s1 and s2 should be equal") 216 + } 217 + if s1.Equal(s3) { 218 + t.Error("s1 and s3 should not be equal") 219 + } 220 + } 221 + 222 + func TestCollect(t *testing.T) { 223 + s1 := Collect(slices.Values([]int{1, 2})) 224 + s2 := Collect(slices.Values([]int{2, 3})) 225 + 226 + unionSet := Collect(s1.Union(s2)) 227 + if unionSet.Len() != 3 { 228 + t.Errorf("Expected union set length 3, got %d", unionSet.Len()) 229 + } 230 + if !unionSet.Contains(1) || !unionSet.Contains(2) || !unionSet.Contains(3) { 231 + t.Error("Union set should contain 1, 2, and 3") 232 + } 233 + 234 + diffSet := Collect(s1.Difference(s2)) 235 + if diffSet.Len() != 1 { 236 + t.Errorf("Expected difference set length 1, got %d", diffSet.Len()) 237 + } 238 + if !diffSet.Contains(1) { 239 + t.Error("Difference set should contain 1") 240 + } 241 + } 242 + 243 + func TestPropertySingleonLen(t *testing.T) { 244 + f := func(item int) bool { 245 + single := Singleton(item) 246 + return single.Len() == 1 247 + } 248 + 249 + if err := quick.Check(f, nil); err != nil { 250 + t.Error(err) 251 + } 252 + } 253 + 254 + func TestPropertyInsertIdempotent(t *testing.T) { 255 + f := func(s Set[int], item int) bool { 256 + clone := s.Clone() 257 + 258 + clone.Insert(item) 259 + firstLen := clone.Len() 260 + 261 + clone.Insert(item) 262 + secondLen := clone.Len() 263 + 264 + return firstLen == secondLen 265 + } 266 + 267 + if err := quick.Check(f, nil); err != nil { 268 + t.Error(err) 269 + } 270 + } 271 + 272 + func TestPropertyUnionCommutative(t *testing.T) { 273 + f := func(s1 Set[int], s2 Set[int]) bool { 274 + union1 := Collect(s1.Union(s2)) 275 + union2 := Collect(s2.Union(s1)) 276 + return union1.Equal(union2) 277 + } 278 + 279 + if err := quick.Check(f, nil); err != nil { 280 + t.Error(err) 281 + } 282 + } 283 + 284 + func TestPropertyIntersectionCommutative(t *testing.T) { 285 + f := func(s1 Set[int], s2 Set[int]) bool { 286 + inter1 := Collect(s1.Intersection(s2)) 287 + inter2 := Collect(s2.Intersection(s1)) 288 + return inter1.Equal(inter2) 289 + } 290 + 291 + if err := quick.Check(f, nil); err != nil { 292 + t.Error(err) 293 + } 294 + } 295 + 296 + func TestPropertyCloneEquals(t *testing.T) { 297 + f := func(s Set[int]) bool { 298 + clone := s.Clone() 299 + return s.Equal(clone) 300 + } 301 + 302 + if err := quick.Check(f, nil); err != nil { 303 + t.Error(err) 304 + } 305 + } 306 + 307 + func TestPropertyIntersectionIsSubset(t *testing.T) { 308 + f := func(s1 Set[int], s2 Set[int]) bool { 309 + inter := Collect(s1.Intersection(s2)) 310 + return inter.IsSubset(s1) && inter.IsSubset(s2) 311 + } 312 + 313 + if err := quick.Check(f, nil); err != nil { 314 + t.Error(err) 315 + } 316 + } 317 + 318 + func TestPropertyUnionIsSuperset(t *testing.T) { 319 + f := func(s1 Set[int], s2 Set[int]) bool { 320 + union := Collect(s1.Union(s2)) 321 + return union.IsSuperset(s1) && union.IsSuperset(s2) 322 + } 323 + 324 + if err := quick.Check(f, nil); err != nil { 325 + t.Error(err) 326 + } 327 + } 328 + 329 + func TestPropertyDifferenceDisjoint(t *testing.T) { 330 + f := func(s1 Set[int], s2 Set[int]) bool { 331 + diff := Collect(s1.Difference(s2)) 332 + return diff.IsDisjoint(s2) 333 + } 334 + 335 + if err := quick.Check(f, nil); err != nil { 336 + t.Error(err) 337 + } 338 + } 339 + 340 + func TestPropertySymmetricDifferenceCommutative(t *testing.T) { 341 + f := func(s1 Set[int], s2 Set[int]) bool { 342 + symDiff1 := Collect(s1.SymmetricDifference(s2)) 343 + symDiff2 := Collect(s2.SymmetricDifference(s1)) 344 + return symDiff1.Equal(symDiff2) 345 + } 346 + 347 + if err := quick.Check(f, nil); err != nil { 348 + t.Error(err) 349 + } 350 + } 351 + 352 + func TestPropertyRemoveWorks(t *testing.T) { 353 + f := func(s Set[int], item int) bool { 354 + clone := s.Clone() 355 + clone.Insert(item) 356 + clone.Remove(item) 357 + return !clone.Contains(item) 358 + } 359 + 360 + if err := quick.Check(f, nil); err != nil { 361 + t.Error(err) 362 + } 363 + } 364 + 365 + func TestPropertyClearEmpty(t *testing.T) { 366 + f := func(s Set[int]) bool { 367 + s.Clear() 368 + return s.IsEmpty() && s.Len() == 0 369 + } 370 + 371 + if err := quick.Check(f, nil); err != nil { 372 + t.Error(err) 373 + } 374 + } 375 + 376 + func TestPropertyIsSubsetReflexive(t *testing.T) { 377 + f := func(s Set[int]) bool { 378 + return s.IsSubset(s) 379 + } 380 + 381 + if err := quick.Check(f, nil); err != nil { 382 + t.Error(err) 383 + } 384 + } 385 + 386 + func TestPropertyDeMorganUnion(t *testing.T) { 387 + f := func(s1 Set[int], s2 Set[int], universe Set[int]) bool { 388 + // create a universe that contains both sets 389 + u := universe.Clone() 390 + for item := range s1.All() { 391 + u.Insert(item) 392 + } 393 + for item := range s2.All() { 394 + u.Insert(item) 395 + } 396 + 397 + // (A u B)' = A' n B' 398 + union := Collect(s1.Union(s2)) 399 + complementUnion := Collect(u.Difference(union)) 400 + 401 + complementS1 := Collect(u.Difference(s1)) 402 + complementS2 := Collect(u.Difference(s2)) 403 + intersectionComplements := Collect(complementS1.Intersection(complementS2)) 404 + 405 + return complementUnion.Equal(intersectionComplements) 406 + } 407 + 408 + if err := quick.Check(f, nil); err != nil { 409 + t.Error(err) 410 + } 411 + }
+1
spindle/db/repos.go
··· 16 16 if err != nil { 17 17 return nil, err 18 18 } 19 + defer rows.Close() 19 20 20 21 var knots []string 21 22 for rows.Next() {
+22 -21
spindle/engine/engine.go
··· 3 3 import ( 4 4 "context" 5 5 "errors" 6 - "fmt" 7 6 "log/slog" 7 + "sync" 8 8 9 9 securejoin "github.com/cyphar/filepath-securejoin" 10 - "golang.org/x/sync/errgroup" 11 10 "tangled.org/core/notifier" 12 11 "tangled.org/core/spindle/config" 13 12 "tangled.org/core/spindle/db" ··· 31 30 } 32 31 } 33 32 34 - eg, ctx := errgroup.WithContext(ctx) 33 + var wg sync.WaitGroup 35 34 for eng, wfs := range pipeline.Workflows { 36 35 workflowTimeout := eng.WorkflowTimeout() 37 36 l.Info("using workflow timeout", "timeout", workflowTimeout) 38 37 39 38 for _, w := range wfs { 40 - eg.Go(func() error { 39 + wg.Add(1) 40 + go func() { 41 + defer wg.Done() 42 + 41 43 wid := models.WorkflowId{ 42 44 PipelineId: pipelineId, 43 45 Name: w.Name, ··· 45 47 46 48 err := db.StatusRunning(wid, n) 47 49 if err != nil { 48 - return err 50 + l.Error("failed to set workflow status to running", "wid", wid, "err", err) 51 + return 49 52 } 50 53 51 54 err = eng.SetupWorkflow(ctx, wid, &w) ··· 61 64 62 65 dbErr := db.StatusFailed(wid, err.Error(), -1, n) 63 66 if dbErr != nil { 64 - return dbErr 67 + l.Error("failed to set workflow status to failed", "wid", wid, "err", dbErr) 65 68 } 66 - return err 69 + return 67 70 } 68 71 defer eng.DestroyWorkflow(ctx, wid) 69 72 70 - wfLogger, err := models.NewWorkflowLogger(cfg.Server.LogDir, wid) 73 + secretValues := make([]string, len(allSecrets)) 74 + for i, s := range allSecrets { 75 + secretValues[i] = s.Value 76 + } 77 + wfLogger, err := models.NewWorkflowLogger(cfg.Server.LogDir, wid, secretValues) 71 78 if err != nil { 72 79 l.Warn("failed to setup step logger; logs will not be persisted", "error", err) 73 80 wfLogger = nil ··· 99 106 if errors.Is(err, ErrTimedOut) { 100 107 dbErr := db.StatusTimeout(wid, n) 101 108 if dbErr != nil { 102 - return dbErr 109 + l.Error("failed to set workflow status to timeout", "wid", wid, "err", dbErr) 103 110 } 104 111 } else { 105 112 dbErr := db.StatusFailed(wid, err.Error(), -1, n) 106 113 if dbErr != nil { 107 - return dbErr 114 + l.Error("failed to set workflow status to failed", "wid", wid, "err", dbErr) 108 115 } 109 116 } 110 - 111 - return fmt.Errorf("starting steps image: %w", err) 117 + return 112 118 } 113 119 } 114 120 115 121 err = db.StatusSuccess(wid, n) 116 122 if err != nil { 117 - return err 123 + l.Error("failed to set workflow status to success", "wid", wid, "err", err) 118 124 } 119 - 120 - return nil 121 - }) 125 + }() 122 126 } 123 127 } 124 128 125 - if err := eg.Wait(); err != nil { 126 - l.Error("failed to run one or more workflows", "err", err) 127 - } else { 128 - l.Info("successfully ran full pipeline") 129 - } 129 + wg.Wait() 130 + l.Info("all workflows completed") 130 131 }
+5 -3
spindle/engines/nixery/engine.go
··· 294 294 workflowEnvs.AddEnv(s.Key, s.Value) 295 295 } 296 296 297 - step := w.Steps[idx].(Step) 297 + step := w.Steps[idx] 298 298 299 299 select { 300 300 case <-ctx.Done(): ··· 303 303 } 304 304 305 305 envs := append(EnvVars(nil), workflowEnvs...) 306 - for k, v := range step.environment { 307 - envs.AddEnv(k, v) 306 + if nixStep, ok := step.(Step); ok { 307 + for k, v := range nixStep.environment { 308 + envs.AddEnv(k, v) 309 + } 308 310 } 309 311 envs.AddEnv("HOME", homeDir) 310 312
+6 -1
spindle/models/logger.go
··· 12 12 type WorkflowLogger struct { 13 13 file *os.File 14 14 encoder *json.Encoder 15 + mask *SecretMask 15 16 } 16 17 17 - func NewWorkflowLogger(baseDir string, wid WorkflowId) (*WorkflowLogger, error) { 18 + func NewWorkflowLogger(baseDir string, wid WorkflowId, secretValues []string) (*WorkflowLogger, error) { 18 19 path := LogFilePath(baseDir, wid) 19 20 20 21 file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) ··· 25 26 return &WorkflowLogger{ 26 27 file: file, 27 28 encoder: json.NewEncoder(file), 29 + mask: NewSecretMask(secretValues), 28 30 }, nil 29 31 } 30 32 ··· 62 64 63 65 func (w *dataWriter) Write(p []byte) (int, error) { 64 66 line := strings.TrimRight(string(p), "\r\n") 67 + if w.logger.mask != nil { 68 + line = w.logger.mask.Mask(line) 69 + } 65 70 entry := NewDataLogLine(w.idx, line, w.stream) 66 71 if err := w.logger.encoder.Encode(entry); err != nil { 67 72 return 0, err
+51
spindle/models/secret_mask.go
··· 1 + package models 2 + 3 + import ( 4 + "encoding/base64" 5 + "strings" 6 + ) 7 + 8 + // SecretMask replaces secret values in strings with "***". 9 + type SecretMask struct { 10 + replacer *strings.Replacer 11 + } 12 + 13 + // NewSecretMask creates a mask for the given secret values. 14 + // Also registers base64-encoded variants of each secret. 15 + func NewSecretMask(values []string) *SecretMask { 16 + var pairs []string 17 + 18 + for _, value := range values { 19 + if value == "" { 20 + continue 21 + } 22 + 23 + pairs = append(pairs, value, "***") 24 + 25 + b64 := base64.StdEncoding.EncodeToString([]byte(value)) 26 + if b64 != value { 27 + pairs = append(pairs, b64, "***") 28 + } 29 + 30 + b64NoPad := strings.TrimRight(b64, "=") 31 + if b64NoPad != b64 && b64NoPad != value { 32 + pairs = append(pairs, b64NoPad, "***") 33 + } 34 + } 35 + 36 + if len(pairs) == 0 { 37 + return nil 38 + } 39 + 40 + return &SecretMask{ 41 + replacer: strings.NewReplacer(pairs...), 42 + } 43 + } 44 + 45 + // Mask replaces all registered secret values with "***". 46 + func (m *SecretMask) Mask(input string) string { 47 + if m == nil || m.replacer == nil { 48 + return input 49 + } 50 + return m.replacer.Replace(input) 51 + }
+135
spindle/models/secret_mask_test.go
··· 1 + package models 2 + 3 + import ( 4 + "encoding/base64" 5 + "testing" 6 + ) 7 + 8 + func TestSecretMask_BasicMasking(t *testing.T) { 9 + mask := NewSecretMask([]string{"mysecret123"}) 10 + 11 + input := "The password is mysecret123 in this log" 12 + expected := "The password is *** in this log" 13 + 14 + result := mask.Mask(input) 15 + if result != expected { 16 + t.Errorf("expected %q, got %q", expected, result) 17 + } 18 + } 19 + 20 + func TestSecretMask_Base64Encoded(t *testing.T) { 21 + secret := "mysecret123" 22 + mask := NewSecretMask([]string{secret}) 23 + 24 + b64 := base64.StdEncoding.EncodeToString([]byte(secret)) 25 + input := "Encoded: " + b64 26 + expected := "Encoded: ***" 27 + 28 + result := mask.Mask(input) 29 + if result != expected { 30 + t.Errorf("expected %q, got %q", expected, result) 31 + } 32 + } 33 + 34 + func TestSecretMask_Base64NoPadding(t *testing.T) { 35 + // "test" encodes to "dGVzdA==" with padding 36 + secret := "test" 37 + mask := NewSecretMask([]string{secret}) 38 + 39 + b64NoPad := "dGVzdA" // base64 without padding 40 + input := "Token: " + b64NoPad 41 + expected := "Token: ***" 42 + 43 + result := mask.Mask(input) 44 + if result != expected { 45 + t.Errorf("expected %q, got %q", expected, result) 46 + } 47 + } 48 + 49 + func TestSecretMask_MultipleSecrets(t *testing.T) { 50 + mask := NewSecretMask([]string{"password1", "apikey123"}) 51 + 52 + input := "Using password1 and apikey123 for auth" 53 + expected := "Using *** and *** for auth" 54 + 55 + result := mask.Mask(input) 56 + if result != expected { 57 + t.Errorf("expected %q, got %q", expected, result) 58 + } 59 + } 60 + 61 + func TestSecretMask_MultipleOccurrences(t *testing.T) { 62 + mask := NewSecretMask([]string{"secret"}) 63 + 64 + input := "secret appears twice: secret" 65 + expected := "*** appears twice: ***" 66 + 67 + result := mask.Mask(input) 68 + if result != expected { 69 + t.Errorf("expected %q, got %q", expected, result) 70 + } 71 + } 72 + 73 + func TestSecretMask_ShortValues(t *testing.T) { 74 + mask := NewSecretMask([]string{"abc", "xy", ""}) 75 + 76 + if mask == nil { 77 + t.Fatal("expected non-nil mask") 78 + } 79 + 80 + input := "abc xy test" 81 + expected := "*** *** test" 82 + result := mask.Mask(input) 83 + if result != expected { 84 + t.Errorf("expected %q, got %q", expected, result) 85 + } 86 + } 87 + 88 + func TestSecretMask_NilMask(t *testing.T) { 89 + var mask *SecretMask 90 + 91 + input := "some input text" 92 + result := mask.Mask(input) 93 + if result != input { 94 + t.Errorf("expected %q, got %q", input, result) 95 + } 96 + } 97 + 98 + func TestSecretMask_EmptyInput(t *testing.T) { 99 + mask := NewSecretMask([]string{"secret"}) 100 + 101 + result := mask.Mask("") 102 + if result != "" { 103 + t.Errorf("expected empty string, got %q", result) 104 + } 105 + } 106 + 107 + func TestSecretMask_NoMatch(t *testing.T) { 108 + mask := NewSecretMask([]string{"secretvalue"}) 109 + 110 + input := "nothing to mask here" 111 + result := mask.Mask(input) 112 + if result != input { 113 + t.Errorf("expected %q, got %q", input, result) 114 + } 115 + } 116 + 117 + func TestSecretMask_EmptySecretsList(t *testing.T) { 118 + mask := NewSecretMask([]string{}) 119 + 120 + if mask != nil { 121 + t.Error("expected nil mask for empty secrets list") 122 + } 123 + } 124 + 125 + func TestSecretMask_EmptySecretsFiltered(t *testing.T) { 126 + mask := NewSecretMask([]string{"ab", "validpassword", "", "xyz"}) 127 + 128 + input := "Using validpassword here" 129 + expected := "Using *** here" 130 + 131 + result := mask.Mask(input) 132 + if result != expected { 133 + t.Errorf("expected %q, got %q", expected, result) 134 + } 135 + }
+6 -1
types/commit.go
··· 174 174 175 175 func (commit Commit) CoAuthors() []object.Signature { 176 176 var coAuthors []object.Signature 177 - 177 + seen := make(map[string]bool) 178 178 matches := coAuthorRegex.FindAllStringSubmatch(commit.Message, -1) 179 179 180 180 for _, match := range matches { 181 181 if len(match) >= 3 { 182 182 name := strings.TrimSpace(match[1]) 183 183 email := strings.TrimSpace(match[2]) 184 + 185 + if seen[email] { 186 + continue 187 + } 188 + seen[email] = true 184 189 185 190 coAuthors = append(coAuthors, object.Signature{ 186 191 Name: name,