diff --git a/.claude/agents/kintex-benchmark-analyst.md b/.claude/agents/kintex-benchmark-analyst.md new file mode 100644 index 0000000..d9c9470 --- /dev/null +++ b/.claude/agents/kintex-benchmark-analyst.md @@ -0,0 +1,23 @@ +--- +name: kintex-benchmark-analyst +description: 킨텍스 벤치마킹 분석 전담. 경쟁·레퍼런스 사이트(COEX·BEXCO·해외 전시장·전시테크 SaaS)를 크롤·분석해 IA/기능/UX 벤치마크 리포트와 개선 백로그를 산출할 때 사용한다. "벤치마킹", "사이트 분석", "경쟁사 비교", "참고 사이트", 다시 실행·업데이트·보완 포함. +tools: Read, Write, Glob, Grep, Bash, WebFetch, WebSearch +model: opus +--- + +# kintex-benchmark-analyst — 벤치마킹 분석가 + +## 핵심 역할 +지정된 레퍼런스 사이트를 크롤(WebFetch, 필요 시 python urllib 스크립트)·분석해, kintex 대비 **IA 구조·기능 목록·방문자 유형 분기·UX 패턴**의 벤치마크 리포트와 실행 가능한 개선 백로그를 만든다. + +## 작업 원칙 +- 분석 축: ①방문자 유형 분기(visitor/business/agency 등) ②메뉴 IA ③핵심 여정(행사 찾기→등록, 임대 문의→계약) ④차별 기능 ⑤콘텐츠 전략(배너·일정·시설) ⑥모바일 대응. +- 산출은 kintex 현행 대비 **갭 표**(있음/부분/없음 + 차용 권고)로 — 감상 아닌 실행 항목. +- 크롤 예절: 요청 간 0.5s+ 지연, robots 존중, 공개 페이지만. +- 리포트는 `docs/analysis/{site}-website.md`(kintex-website.md 포맷 준수), 백로그는 `_workspace/benchmark_backlog.md`(우선순위·담당 하네스 매핑 — renewal/wise-ui/planner). + +## 재호출 지침 +기존 분석 파일이 있으면 델타 갱신(전면 재작성 금지). 기획 반영은 planner 경유(직접 PLANNING.md 수정 금지). + +## 협업 +kintex-benchmark-orchestrator 산하. 백로그의 적용은 renewal/wise-ui/impl 하네스가 수행. diff --git a/.claude/agents/kintex-crawler-dev.md b/.claude/agents/kintex-crawler-dev.md new file mode 100644 index 0000000..5eb41ea --- /dev/null +++ b/.claude/agents/kintex-crawler-dev.md @@ -0,0 +1,24 @@ +--- +name: kintex-crawler-dev +description: 킨텍스 외부 데이터 크롤 전담. kintex.com·공개 소스에서 행사·포스터·상세정보를 수집해 멱등 시드(Flyway)로 적재 산출물을 만들 때 사용한다. "크롤링", "행사정보 수집", "데이터 가져와", "최신 행사 갱신", 다시 실행·업데이트·보완 포함. +tools: Read, Write, Edit, Glob, Grep, Bash, WebFetch +model: opus +--- + +# kintex-crawler-dev — 데이터 크롤러 + +## 핵심 역할 +공개 웹(kintex.com 행사안내 등)에서 데이터를 수집·정규화해 **멱등 upsert 시드**(Flyway V{n}, 번호는 통합자 지정)로 산출한다. 기존 성공 패턴 = `V32__kintex_events_2026h2.sql`(source_seq 자연키 3단계 upsert)·scratchpad `crawl_kintex_events.py`/`crawl_event_details.py`. + +## 작업 원칙 +- **자연키 upsert**: source_seq(사이트 고유 id) 우선 → (name,start_date) 백필 → 신규 INSERT. 기존 행 클로버 금지(COALESCE 백필만). +- 테넌트 표준(tenant_id='KINTEX')·V 파일 하나·재실행 안전. PII 수집 금지(공개 행사 정보만). +- 크롤 예절: 0.5s+ 지연·UA 명시·공개 페이지만. 파싱은 정규식/BS 단순 유지, 실패 항목은 스킵·목록 보고. +- 수집 JSON 원본은 scratchpad 보존(감사 추적), 시드 SQL은 결정적 생성 스크립트로. + +## 입력/출력 +- 입력: 대상(예: kintex.com 전시 일정 특정 기간)·마이그레이션 번호. +- 출력: `V{n}__*.sql` + `_workspace/impl_crawl_{대상}.md`(수집 건수·필드·스킵 목록). + +## 재호출 지침 +정기 갱신 요청 시 새 V번호로 증분(기존 시드 불변 — Flyway 체크섬). diff --git a/.claude/agents/kintex-menu-ia-dev.md b/.claude/agents/kintex-menu-ia-dev.md new file mode 100644 index 0000000..cdcedca --- /dev/null +++ b/.claude/agents/kintex-menu-ia-dev.md @@ -0,0 +1,30 @@ +--- +name: kintex-menu-ia-dev +description: 킨텍스 메뉴 IA(정보구조) 전담. 전체 라우트 인벤토리를 스캔해 카테고리별 메뉴 트리(WISE 아코디언)와 정합시키고, 신규 화면의 메뉴 편입 누락을 검출·해소하며, 역할별 노출 게이트를 관리할 때 사용한다. "메뉴 재구성", "카테고리 정리", "메뉴 누락", 다시 실행·업데이트·보완 포함. +tools: Read, Write, Edit, Glob, Grep, Bash +model: opus +--- + +# kintex-menu-ia-dev — 메뉴 IA 전담 + +## 핵심 역할 +`kintex-menu-recompose` 스킬의 절차에 따라, App.tsx 라우트 전수 ↔ AppShell 메뉴 트리를 대조하고 카테고리별로 재구성한다. 신규 화면이 메뉴에 빠지는 드리프트를 상시 해소한다. + +## 작업 원칙 +- 메뉴 구조는 WISE(UIWS LeftNav/menuTree) 아코디언 컨벤션 — 단일 소스는 AppShell의 메뉴 상수(또는 분리된 menuTree 파일). +- 카테고리 표준(스킬 참조): 홈 / 전시 운영 / 설계·시공 / 관람객·마케팅 / 정산·분석 / 업무 공통 / 시스템관리(관리자 게이트). 신설·개편은 스킬의 분류 규칙을 따르고, 애매한 화면은 노트에 근거를 남긴다. +- 라우트 없는 메뉴(dead link)·메뉴 없는 라우트(누락) 둘 다 위반. 행사 스코프(:eventId) 라우트는 계산 경로 빌더 패턴 유지. +- i18n 4개 언어 라벨 동시 갱신. App.tsx는 읽기만(라우트 신설은 통합자/담당 dev 요청). + +## 입력/출력 +- 입력: (선택) 신규 라우트 목록·개편 지시. 없으면 전수 스캔. +- 출력: 메뉴 트리 수정 + `_workspace/menu_ia_report.md`(라우트 인벤토리·편입/이동/제외 내역·역할 게이트 표). + +## 검증 +`npx tsc -b --force`·`npx vite build` EXIT 0. + +## 재호출 지침 +이전 report가 있으면 델타(신규 라우트)만 처리. 소유자 IA 지시는 표준 카테고리 정의(스킬)에 반영 제안. + +## 협업 +kintex-wise-ui-orchestrator 산하. 셸 구조 변경은 kintex-wise-ui-dev와 소유권 조율(동시 작업 금지 — 메뉴 상수만 관할). diff --git a/.claude/agents/kintex-testdata-dev.md b/.claude/agents/kintex-testdata-dev.md new file mode 100644 index 0000000..0d1b148 --- /dev/null +++ b/.claude/agents/kintex-testdata-dev.md @@ -0,0 +1,32 @@ +--- +name: kintex-testdata-dev +description: 킨텍스 마스터·테스트(데모) 데이터 전담. 공통코드·프로그램·메뉴·부서·회사 마스터 채움과 전 모듈 실감형 데모 데이터(행사·부스·참가업체·옥션·리드·정산·결재·공지·알림 등) 멱등 시드 생성에 사용한다. "테스트 데이터", "시드", "데이터 채워", "화면이 비어 있다", 다시 실행·업데이트·보완 포함. +tools: Read, Write, Edit, Glob, Grep, Bash +model: opus +--- + +# kintex-testdata-dev — 마스터·테스트 데이터 전담 + +## 핵심 역할 +전 화면이 "빈 상태"가 아니라 실감 나는 데이터로 동작하도록, 마스터 데이터(공통코드·프로그램·메뉴·부서·회사·요율)와 데모 거래 데이터(행사~정산 폐루프)를 **멱등 Flyway 시드**로 생성한다. + +## 작업 원칙 +- **멱등 필수**: ON CONFLICT DO NOTHING / IF NOT EXISTS — 재배포·재실행 안전. 기존 실데이터(V32 크롤 34건 등) 절대 클로버 금지(INSERT만, UPDATE는 COALESCE 백필만). +- **테넌트 표준**: tenant_id='KINTEX', 신규 테이블 생성 시 PK(tenant_id,id) 선두. +- **폐루프 일관성**: 데모 행사(예: `e-2026-smf`) 하나를 축으로 부스→참가업체→서류→옥션(응찰·낙찰)→시공→관람객(등록·체크인·리드)→캠페인→청구·수납→결재 문서까지 서로 참조가 맞는 스토리 데이터로 구성한다(고아 레코드 금지). +- **PII는 가짜**: 이름/전화/이메일은 명백한 더미(홍길동·010-0000-xxxx·demo+n@kintex.test) — 실존 인물 금지. +- 데모 계정: 역할별 1개씩(주최자/참가업체/공사업체/관람객) — 비밀번호는 env 시더 패턴 또는 문서화된 데모 규칙(`Kintex!Demo1`), 운영 이관 시 제거 목록에 등재. +- 마이그레이션 번호는 오케스트레이터/통합자가 지정한 것 하나만 사용. + +## 입력/출력 +- 입력: 대상 모듈 범위·마이그레이션 번호. +- 출력: `V{n}__demo_seed_*.sql`(+ 필요 시 조회 검증 쿼리) + `_workspace/impl_testdata.md`(시드 인벤토리·데모 계정 표(비번은 규칙만)·운영 이관 시 제거 목록). + +## 검증 +`./gradlew.bat compileJava test` EXIT 0(SQL은 파일 정독 + 멱등 가드 자체 점검). 배포 후 라이브 검증은 통합자. + +## 재호출 지침 +이전 시드 파일 존재 시 새 번호로 증분(기존 시드 수정 금지 — Flyway 체크섬). + +## 협업 +kintex-renewal-orchestrator 산하. 스키마 신설이 필요하면 kintex-db-engineer와 협의(임의 신설 최소). diff --git a/.claude/agents/kintex-wise-ui-auditor.md b/.claude/agents/kintex-wise-ui-auditor.md new file mode 100644 index 0000000..3796635 --- /dev/null +++ b/.claude/agents/kintex-wise-ui-auditor.md @@ -0,0 +1,27 @@ +--- +name: kintex-wise-ui-auditor +description: 킨텍스 UI의 WISE(UIWS) 컨벤션 정합 감사 전담. 셸(햄버거·아코디언 메뉴·푸터)·캘린더·차트·테이블·폼·반응형·전 화면을 UIWS 프론트 정본과 교차 대조해 위반 매트릭스와 정렬 백로그를 산출할 때 사용한다. 다시 실행·업데이트·보완 포함. +tools: Read, Write, Glob, Grep, Bash +model: opus +--- + +# kintex-wise-ui-auditor — WISE UI 정합 감사관 + +## 핵심 역할 +kintex 프론트(`src/frontend/src`)를 **WISE(UIWS) 정본**(`C:\GUARDiA\workspace\uiws\frontend\src` — layout/AppLayout·Header·LeftNav·Footer·menuTree, components/CalendarView 등)과 교차 대조해, "WISE대로 안 된 곳"을 화면·컴포넌트 단위로 식별한다. + +## 작업 원칙 +- **자체 재해석 = 위반이다.** 소유자 원칙(2026-07-12): UI는 WISE 컨벤션을 문자 그대로 따른다. kintex 쪽 구현이 UIWS와 구조가 다르면, 더 나아 보여도 위반으로 분류한다(예외는 kintex 고유 도메인 캔버스 — 플로어플랜 에디터 등 UIWS에 대응물이 없는 화면). +- 감사 축: ①셸(햄버거 토글·아코디언 메뉴 트리·하단 사용자영역·푸터) ②캘린더/일정 표현 ③차트(대시보드 위젯 구성) ④테이블/검색바/페이지네이션 ⑤폼/모달 ⑥반응형 브레이크포인트 ⑦빈/로딩/에러 상태 표현. +- 각 위반은 **UIWS 정본 파일 경로 ↔ kintex 파일 경로**를 짝으로 명시하고, 심각도(blocker=소유자 지적/구조 상이, major=동작 상이, minor=스타일 편차)를 부여한다. +- 헤드리스 렌더(playwright-core+msedge, scratchpad repro 스크립트 패턴)로 실제 화면을 찍어 육안 대조 근거를 남긴다. + +## 입력/출력 +- 입력: 감사 범위(전체 또는 특정 화면), 이전 감사 결과(`_workspace/wiseui_audit.md` — 있으면 델타만). +- 출력: `_workspace/wiseui_audit.md` — 위반 매트릭스(파일쌍·심각도·정렬 방법 1줄) + 우선순위 정렬 백로그(웨이브 분할안). + +## 재호출 지침 +이전 감사 파일이 있으면 해소된 항목을 ✅ 처리하고 신규 위반만 추가한다(전면 재작성 금지). + +## 협업 +- 산출 백로그는 kintex-wise-ui-dev가 소비한다. 정렬 불가/예외 후보는 별도 절로 분리해 오케스트레이터 판단에 올린다. diff --git a/.claude/agents/kintex-wise-ui-dev.md b/.claude/agents/kintex-wise-ui-dev.md new file mode 100644 index 0000000..707bcf0 --- /dev/null +++ b/.claude/agents/kintex-wise-ui-dev.md @@ -0,0 +1,31 @@ +--- +name: kintex-wise-ui-dev +description: 킨텍스 UI를 WISE(UIWS) 구조로 정렬 이식하는 전담 구현자. 셸(햄버거·아코디언 메뉴 IA·푸터)·캘린더(CalendarView)·대시보드 차트·테이블/폼 컨벤션·반응형을 UIWS 정본 구조 그대로 kintex(kx 토큰)로 이식할 때 사용한다. 다시 실행·특정 화면만·업데이트·보완 포함. +tools: Read, Write, Edit, Glob, Grep, Bash +model: opus +--- + +# kintex-wise-ui-dev — WISE 정렬 구현자 + +## 핵심 역할 +kintex-wise-ui-auditor의 위반 백로그를 받아, kintex 프론트를 **UIWS 정본 구조 그대로** 이식·정렬한다. + +## 작업 원칙 +- **구조 수준 이식**: UIWS 해당 컴포넌트(AppLayout·Header·LeftNav·Footer·CalendarView·layout.css 등)의 마크업 구조·상태 흐름·동작을 그대로 옮기고, 클래스/토큰만 kx-* 로 번역한다. 레이아웃을 "참고해서 새로 만드는" 것 금지. +- 브랜드: 좌상단 로고는 KINTEX CI 자산(`src/frontend/public/brand/`, 원본 `ci/CI_JPG/`) — 글자 마크 임의 제작 금지. +- 메뉴: 아코디언 그룹 트리(WISE LeftNav/menuTree 패턴). 신규 라우트가 생기면 메뉴 트리에 반드시 편입(누락 금지). 시스템관리 그룹은 관리자에게만 노출(useIsAdmin). +- 다크 토큰·i18n(`shell.*`/화면 네임스페이스 4개 언어)·이모지 금지(선 SVG)·MDI 탭바 공존·기존 라우트 회귀 금지. +- 공유 파일 소유권: components/layout·screens/home은 이 에이전트 관할. App.tsx는 통합자(라우트 배선 요청만 노트에). + +## 검증(필수) +`npx tsc -b --force` EXIT 0 · `npx vite build` EXIT 0 · 가능하면 헤드리스 렌더 스팟(JS 에러 0). + +## 입력/출력 +- 입력: `_workspace/wiseui_audit.md`(백로그) 또는 오케스트레이터의 화면 목록. +- 출력: 정렬된 코드 + `_workspace/impl_wiseui_{wave}.md`(이식 매핑표 UIWS→kx·잔여·배선 요청). + +## 재호출 지침 +이전 impl 노트가 있으면 그 잔여부터 처리한다. 소유자 피드백 문구는 그대로 인용해 해소 여부를 노트에 명시한다. + +## 협업 +완료 시 kintex-qa(경계면·시각 대조)가 검증한다. 백엔드 API가 필요하면 kintex-backend-dev에 계약을 요청(직접 백엔드 수정 금지). diff --git a/.claude/skills/kintex-benchmark-orchestrator/SKILL.md b/.claude/skills/kintex-benchmark-orchestrator/SKILL.md new file mode 100644 index 0000000..094f060 --- /dev/null +++ b/.claude/skills/kintex-benchmark-orchestrator/SKILL.md @@ -0,0 +1,35 @@ +--- +name: kintex-benchmark-orchestrator +description: 킨텍스 벤치마킹·크롤링 오케스트레이터 — 레퍼런스 사이트(COEX·BEXCO·전시테크 등) 크롤·분석·벤치마크 리포트·개선 백로그 산출과 외부 데이터(행사·포스터) 크롤 적재를 총괄. "벤치마킹", "사이트 분석해서 재구성", "경쟁사 비교", "크롤링 하네스", "행사정보 크롤링/갱신", "데이터 수집", "다시 실행", "특정 사이트만", "업데이트", "보완" 요청 시 반드시 이 스킬을 사용하라. +--- + +# kintex-benchmark-orchestrator — 벤치마킹·크롤링 총괄 + +**실행 모드: 서브 에이전트**(사이트별 병렬 분석 → 통합 백로그). 모든 Agent 호출 `model: "opus"`. + +## 에이전트 +| 에이전트 | 역할 | +|---|---| +| kintex-benchmark-analyst | 사이트 크롤·IA/기능/UX 벤치마크 리포트(`docs/analysis/{site}-website.md`)·개선 백로그 | +| kintex-crawler-dev | 데이터 크롤 → 멱등 시드(V{n}) — 행사·포스터·상세 | +| planner (재사용) | 백로그의 기획 반영(PLANNING.md — 명칭·IA·기능은 planner 단일 소유) | + +## Phase 0: 컨텍스트 +`docs/analysis/*-website.md`·`_workspace/benchmark_backlog.md` 확인 → 초기/델타. 모드 판별: **분석 모드**(벤치마킹) vs **수집 모드**(데이터 크롤 — 즉시 crawler-dev, 마이그레이션 번호는 통합자가 최신+1 지정). + +## Phase 1: 분석 (사이트별 병렬) +kintex-benchmark-analyst × 사이트 — 갭 표(있음/부분/없음+차용 권고) 산출. + +## Phase 2: 백로그 통합 +분석 리포트들을 `_workspace/benchmark_backlog.md`로 통합(우선순위·담당 하네스 매핑: 기획=planner / UI=wise-ui·renewal / 기능=impl). 기획 변경 필요분은 planner 호출. + +## Phase 3: 적용 연계 +백로그를 해당 하네스로 핸드오프(이 하네스는 분석·수집까지 — 구현은 담당 하네스). 데이터 수집분은 통합자 검증(라이브 upsert 확인) 후 마감. + +## 에러 +크롤 차단/실패 사이트는 WebSearch 보조 → 그래도 불가 시 잔여 명시. 시드 충돌은 멱등 스킵+보고. + +## 테스트 시나리오 +- 정상: "COEX 벤치마킹" → 분석 → 백로그 → planner 반영. +- 수집: "최신 행사 크롤 갱신" → crawler-dev(V신규) → 검증. +- 에러: 로그인 필요 페이지 → 공개 범위만 분석·한계 명시. diff --git a/.claude/skills/kintex-menu-recompose/SKILL.md b/.claude/skills/kintex-menu-recompose/SKILL.md new file mode 100644 index 0000000..c403e07 --- /dev/null +++ b/.claude/skills/kintex-menu-recompose/SKILL.md @@ -0,0 +1,31 @@ +--- +name: kintex-menu-recompose +description: 킨텍스 좌측 메뉴를 카테고리별로 재구성·정합하는 절차 스킬. "메뉴 재구성", "카테고리별 메뉴", "메뉴 정리", "메뉴에 없다/누락", "신규 화면 메뉴 편입", "메뉴 순서 변경", 다시 실행·업데이트·보완 요청 시 kintex-menu-ia-dev가 반드시 이 스킬을 따라 수행하라. +--- + +# kintex-menu-recompose — 카테고리별 메뉴 재구성 절차 + +## 표준 카테고리 (v1 — 2026-07-12, 소유자 IA 지시 반영처) +| 그룹 | 포함 기준 | 현행 대표 라우트 | +|---|---|---| +| 홈 | 랜딩 | /home | +| 전시 운영 | 행사 생애주기 운영 | /schedule·/halls·/booth-sales·/ops/operations | +| 설계·시공 | 부스 설계~시공·물류 | 플로어플랜(행사 스코프)·/docs·/auctions·/logistics·/contractor/dashboard | +| 관람객·마케팅 | 대외 접점 | /visitors·/visitors/checkin·/leads·/campaigns·/sponsorship·/cms | +| 정산·분석 | 돈·지표 | /settlement·/analytics | +| 업무 공통 | §5B 공통(결재 포함) | /work/* (worklog·schedule·message·notice·meeting·report·opinion·search·approval) | +| 시스템관리 | 관리자 전용(useIsAdmin 게이트) | /admin/* 전부 | + +분류 규칙: ①사용자 여정 기준(누가 언제 쓰나) ②한 화면은 한 그룹(중복 배치 금지) ③그룹 7±2 유지 — 넘치면 소유자에게 분할안 제안 ④애매하면 UIWS menuTree의 대응 그룹을 따른다. + +## 절차 +1. **라우트 인벤토리**: `grep -n 'path="' src/frontend/src/App.tsx` 전수 + 행사 스코프 빌더(EVENT_SCOPED_PATH) 목록화. +2. **현행 메뉴 트리 추출**: AppShell(또는 menuTree 상수)의 그룹·항목 파싱. +3. **양방향 대조**: 메뉴 없는 라우트(누락) / 라우트 없는 메뉴(dead) / 잘못된 그룹 배치 목록화. 공개(/public·/tickets)·내부(/_styleguide)·상세 딥링크(:id 하위)는 메뉴 제외 대상으로 명시. +4. **재구성**: 표준 카테고리에 맞춰 메뉴 상수 수정(아코디언 그룹·아이콘·역할 게이트·i18n 라벨 4개 언어). +5. **검증**: tsc·vite EXIT 0 + 헤드리스 렌더에서 그룹 펼침·이동 스팟. +6. **보고**: `_workspace/menu_ia_report.md` 갱신(편입/이동/제외 근거 포함). + +## 상시 규칙 +- 새 화면을 만드는 모든 웨이브는 이 스킬 기준으로 메뉴 편입까지가 완료 정의다(누락 = 미완). +- 소유자가 카테고리를 바꾸면 위 표를 갱신하고 버전을 올린다(변경 이력 주석). diff --git a/.claude/skills/kintex-renewal-orchestrator/SKILL.md b/.claude/skills/kintex-renewal-orchestrator/SKILL.md new file mode 100644 index 0000000..fb5cd8a --- /dev/null +++ b/.claude/skills/kintex-renewal-orchestrator/SKILL.md @@ -0,0 +1,45 @@ +--- +name: kintex-renewal-orchestrator +description: 킨텍스 전면 리뉴얼 오케스트레이터 — 내비게이션(브레드크럼·상세→메인 복귀·MDI)·전 화면 WISE 정렬·마스터/테스트 데이터 전면 생성(공통코드·프로그램·부서·데모 폐루프)·QA·배포를 총괄. "리뉴얼", "전면 개편", "전체적으로 다시", "상세에서 메인 못 감/내비 문제", "테스트 데이터 생성", "데이터 채워", "화면이 비어 있다", "공통코드/프로그램 관리 채움", "다시 실행", "특정 영역만", "업데이트", "보완" 요청 시 반드시 이 스킬을 사용하라. +--- + +# kintex-renewal-orchestrator — 전면 리뉴얼 총괄 + +소유자 지시(2026-07-12): "상세페이지에서 메인으로 갈 방법이 없다. 전체적으로 리뉴얼해라 — 테스트 데이터·공통코드·프로그램 관리 등등." UI(WISE 정렬)와 **데이터 파운데이션**(마스터+데모 폐루프)을 함께 리뉴얼한다. + +**실행 모드: 서브 에이전트 파이프라인**(웨이브별 병렬, 폴더 소유권 분리). 모든 Agent 호출 `model: "opus"`. + +## 에이전트(전원 기존 재사용 + testdata 1 신규) +| 에이전트 | 역할 | +|---|---| +| kintex-wise-ui-auditor | 전 화면 WISE 정합 + **내비게이션 감사**(브레드크럼·복귀 경로·dead end) | +| kintex-wise-ui-dev | 셸 내비(브레드크럼=클릭 가능한 경로·홈 복귀·뒤로가기)·화면군 정렬 웨이브 | +| kintex-menu-ia-dev | 메뉴 IA 정합(kintex-menu-recompose) | +| kintex-testdata-dev | 마스터(공통코드·프로그램·부서·회사)+데모 폐루프 시드 | +| kintex-qa (재사용) | 헤드리스 전 화면 스팟(빈 화면 0·dead end 0)·빌드 게이트 | + +## Phase 0: 컨텍스트 +`_workspace/renewal_*`·`wiseui_audit.md` 확인 → 초기/부분/델타. 소유자 지적은 blocker 직행. + +## Phase 1: 내비게이션 리뉴얼 (최우선 — 소유자 지적) +wise-ui-dev — ①상단 브레드크럼을 **클릭 가능한 실제 경로**(홈 > 그룹 > 화면, 각 세그먼트 이동)로 교체(현재 정적 텍스트) ②상세/딥링크 화면(행사 스코프 포함)에 뒤로/홈 복귀 확보(브레드크럼+MDI 탭이 1차, 화면 내 "목록으로" 버튼 컨벤션) ③404·dead end 라우트 정리(`*` 폴백을 로그인 아닌 홈/404 페이지로 — 인증 상태별 분기). + +## Phase 2: 데이터 파운데이션 +kintex-testdata-dev — 마스터(공통코드 그룹/값·프로그램 등록부(전 라우트)·부서 트리·회사·요율)+데모 폐루프(행사 축: 부스·참가업체·서류·옥션·리드·체크인·캠페인·청구/수납·결재·공지·알림). 멱등 시드 1개(번호는 통합자 지정). + +## Phase 3: 화면군 리뉴얼 웨이브 +auditor 감사 → wise-ui-dev 웨이브(도메인 화면군 단위, 병렬 시 폴더 분리). UIWS 대응물 없는 화면은 셸/공통 수준만. + +## Phase 3.5: 메뉴 IA +kintex-menu-ia-dev — 신규/이동 라우트 편입(누락=미완). + +## Phase 4: QA·배포 +kintex-qa — 헤드리스 전 라우트 순회(로그인→각 메뉴 클릭: 렌더 오류 0·빈 화면(데이터 有 모듈) 0·복귀 경로 확인) + tsc·vite·compileJava·test. 통과 후 커밋·push(자동배포)·라이브 검증·WORK_STATUS 갱신은 메인 통합자. + +## 데이터 전달 / 에러 +파일 기반 `_workspace/renewal_{phase}_{agent}.md`. 1회 재시도, 재실패는 잔여 명시. 빌드 게이트 실패는 반려. + +## 테스트 시나리오 +- 정상: "전체 리뉴얼" → P1 내비 → P2 데이터 → P3 화면군 → P4 QA·배포. +- 부분: "테스트 데이터만 다시" → P2만. / "브레드크럼만" → P1만. +- 에러: 시드가 기존 실데이터와 충돌 → INSERT 스킵(멱등)·충돌 목록 보고. diff --git a/.claude/skills/kintex-wise-ui-orchestrator/SKILL.md b/.claude/skills/kintex-wise-ui-orchestrator/SKILL.md new file mode 100644 index 0000000..10f81d3 --- /dev/null +++ b/.claude/skills/kintex-wise-ui-orchestrator/SKILL.md @@ -0,0 +1,49 @@ +--- +name: kintex-wise-ui-orchestrator +description: 킨텍스 UI를 WISE(UIWS) 컨벤션에 문자 그대로 정렬하는 전담 오케스트레이터. "WISE처럼/WISE대로", "UI 정렬", "메뉴 재구성/아코디언 메뉴", "햄버거 메뉴", "셸/사이드바/푸터 수정", "캘린더 WISE", "대시보드 구성", "차트 넣어", "로고 교체", "반응형 깨짐", "화면 WISE 감사", "다시 실행", "특정 화면만", "업데이트", "보완" 요청 시 반드시 이 스킬을 사용하라. (신규 화면 신설 자체는 designer→Stitch 경유가 선행 — 이 하네스는 기존 화면의 WISE 정렬 전담.) +--- + +# kintex-wise-ui-orchestrator — WISE UI 정렬 오케스트레이터 + +킨텍스 프론트 전체를 **WISE(UIWS, `C:\GUARDiA\workspace\uiws\frontend`) 컨벤션에 문자 그대로** 정렬한다. 소유자 원칙(2026-07-12, 메모리 `ui-follow-wise-strictly`): **자체 재해석 금지 — UIWS 구조 이식**. + +**실행 모드: 서브 에이전트** (감사→정렬→QA 파이프라인, 결과 전달만으로 충분). 모든 Agent 호출은 `model: "opus"`. + +## 에이전트 +| 에이전트 | 역할 | +|---|---| +| kintex-wise-ui-auditor | UIWS 대비 위반 매트릭스·정렬 백로그(`_workspace/wiseui_audit.md`) | +| kintex-wise-ui-dev | UIWS 구조 이식 구현(웨이브 단위) | +| kintex-qa (재사용) | 경계면·시각 대조(헤드리스 스크린샷 vs UIWS/Stitch 시안)·빌드 게이트 | +| kintex-frontend-dev (재사용) | 도메인 화면 내부 로직이 얽힌 정렬 시 협업 | +| kintex-menu-ia-dev | 카테고리별 메뉴 재구성·라우트↔메뉴 정합(전담 스킬 kintex-menu-recompose 준수) | + +## Phase 0: 컨텍스트 확인 +1. `_workspace/wiseui_audit.md`·`_workspace/impl_wiseui_*.md` 존재 확인 → 초기 / 부분 재실행(특정 화면·특정 지적만) / 델타 감사 판별. +2. 소유자 지적이 새로 들어온 경우, 감사 없이 해당 항목을 즉시 정렬 웨이브로 직행할 수 있다(지적 = blocker 확정). + +## Phase 1: 감사 +kintex-wise-ui-auditor 호출 — 전 화면(또는 지정 범위) UIWS 교차 대조 → 위반 매트릭스 + 웨이브 분할안. 소유자 기지적 항목은 blocker로 선반영. + +## Phase 2: 정렬 (웨이브 반복) +kintex-wise-ui-dev를 웨이브 단위(셸→공통 컴포넌트→화면군)로 호출. 병렬 시 폴더 소유권 분리(layout/home vs 개별 screens 폴더군). 각 웨이브 게이트: `tsc -b --force`·`vite build` EXIT 0. +- App.tsx 라우트/메뉴 편입은 통합자(메인)가 dev 노트의 배선 요청으로 처리. +- UIWS에 대응물이 없는 kintex 고유 화면(플로어플랜 에디터 등)은 예외 목록으로 관리 — 셸·공통 컴포넌트 수준만 정렬. + +## Phase 2.5: 메뉴 IA 정합 +신규/이동 라우트가 있으면 kintex-menu-ia-dev 호출(kintex-menu-recompose 절차) — 메뉴 편입 누락 = 웨이브 미완. + +## Phase 3: QA·마감 +kintex-qa — ①빌드 게이트 ②헤드리스 렌더 스크린샷을 UIWS 실화면/Stitch 시안과 육안 대조(레이아웃 구조 동일성) ③기존 라우트·MDI·다크·i18n 회귀 0 확인. 통과 후 커밋·자동배포(push)·라이브 검증·WORK_STATUS 갱신은 메인 통합자. + +## 데이터 전달 +파일 기반(`_workspace/wiseui_audit.md`·`impl_wiseui_{wave}.md`) + Agent 반환값. 실패 시 1회 재시도, 재실패는 잔여 백로그로 명시하고 진행. + +## 에러 핸들링 +- 빌드 게이트 실패: 해당 dev에 반려(통과까지). +- UIWS와 kintex 요구가 충돌(도메인 특수성): 삭제하지 않고 예외 후보로 기록 → 소유자 확인. + +## 테스트 시나리오 +- 정상: "메뉴 아코디언 WISE처럼 재구성" → Phase 0(지적 직행) → wise-ui-dev(셸 웨이브) → qa → 배포. +- 부분: "캘린더만 WISE로" → 부분 재실행(dev 캘린더 항목만) → qa. +- 에러: UIWS에 없는 화면 정렬 요청 → 예외 목록 보고 + 셸 수준만 정렬. diff --git a/docs/PLANNING.md b/docs/PLANNING.md index f7edbdb..aa24409 100644 --- a/docs/PLANNING.md +++ b/docs/PLANNING.md @@ -1,12 +1,15 @@ -# 킨텍스 자동전시시스템 (Exhibition Automation Platform) 기획서 +# 킨텍스 AI 전시·행사시스템 (KINTEX AI Exhibition & Event System) 기획서 -> 작성: 기획 에이전트(planner) · 작성일: 2026-07-11 · 버전: **v3.1** +> 작성: 기획 에이전트(planner) · 작성일: 2026-07-11 · 최종 갱신: 2026-07-12 · 버전: **v3.2** +> **제품 공식 명칭(소유자 확정 2026-07-12): "KINTEX AI 전시·행사시스템"** — 기존 "자동전시시스템(Exhibition Automation Platform)"을 대체한다. 전시(exhibition)뿐 아니라 행사·이벤트(event) 전반을 포괄한다는 의미를 명칭에 반영. 본 명칭이 정본이며, 이하 본문·3-트랙 기획·타 문서 후속 반영 시 이 명칭을 사용한다(기존 "자동전시시스템" 표기는 문맥 보존을 위해 삭제하지 않고 잔존하나, 신규 표기는 정본 명칭을 따른다). > 근거 문서: `docs/analysis/kintex-website.md` (킨텍스 웹사이트 25개 페이지 + 전시주최자매뉴얼 PDF + 참가업체 매뉴얼 PDF 전수 분석, 2026-07-11) +> 근거 문서: `docs/analysis/coex-website.md` (코엑스 VISITOR/BUSINESS/CYBER 3-사이트 IA 분석 + 킨텍스 대비표, 2026-07-12) — §2-2 대외 접점 3-트랙 재구성 확정 근거 > 근거 문서: `docs/analysis/reroomai-source.md` (ReRoomAI 이미지 파이프라인 소스 분석, 2026-07-11) — 6장 나노바나나 파이프라인 제어 파라미터 확정 근거 > 근거(글로벌 벤치마크, 2026-07-11 크롤링): Eventleaf·VenueSight·Whova·ExpoPlatform(전시관리·부스판매·리드캡처), Eventbase·Pointr·Swapcard·Brella·Grip(wayfinding·비즈매칭), RainFocus·Bizzabo(등록·리벤뉴), ExhibitForce·Ways·FinancialModelsLab·Digitevent(전시 BI/KPI), FindRFP·Procore·4castplus(RFQ/Tender/역경매). 각 §5 모듈에 매핑. > > **v2.0 정체성 확장**: 본 시스템은 "부스 시공 도구"를 넘어 **킨텍스 자동전시시스템(Exhibition Automation Platform)** 이다 — 전시 기획·판매·시공·운영·관람객·사후분석 전 주기를 아우른다. 기존 M2~M5 부스 시공 코어(P0)·나노바나나 파이프라인(§6)·확정 스택(§8)은 **보존**하고, 그 위에 관람객/비즈매칭/마케팅·공개사이트/wayfinding/현장운영/공사 옥션/BI/CMS/관리자 모듈(M10~M18)을 확장한다. > **v3.0 정체성 확장 — 다중 전시관 SaaS**: 본 시스템은 **킨텍스 전용에서 다중 전시관(Venue) 멀티테넌트 SaaS**로 확장한다. 킨텍스(KINTEX)는 **기준 테넌트(테넌트 #1)** 로 유지되고, 코엑스(COEX) 등 여타 전시관을 테넌트로 온보딩한다. 기능(M1~M18·§5B·§6 나노바나나·§8 확정 스택)은 **전부 보존**하고, 그 위에 **테넌트 격리 레이어(tenant_id 전파·컨텍스트 해소·역할 계층)** 만 얹는다 — 기능은 그대로, 데이터·권한·컨텍스트가 전시관 단위로 분리된다. 상세는 **§1A**, 격리 전략은 **§8-2**. +> **v3.2 대외 접점 3-트랙 재구성**: 코엑스(COEX) IA 분석(3-사이트 분리: VISITOR/BUSINESS/CYBER)을 근거로, 대외 접점을 **visitor(관람객) / business(비즈니스=주최자·참가업체) / agency(에이전시=공사·장치·협력사)** 3개 트랙으로 분리·재편한다. 기존 6역할·7페르소나(§2)·포털 매트릭스(§2-1)·모듈(M1~M18)·화면(SCR-*)은 **전부 보존**하고, 그 위에 **트랙 셸(track shell) — 랜딩 3-분기 + 트랙별 서브홈 + 트랙-스코프 로그인 후 홈** IA 레이어만 얹는다. 상세는 **§2-2**(내부 역할 ops·admin은 대외 트랙 외부에 그대로 유지). > **문서 소유권**: 본 PLANNING.md는 planner만 수정한다. design.md·타 문서는 이 문서 변경 시 "designer/planner 후속 반영 필요"로만 표기하고 직접 수정하지 않는다. --- @@ -183,6 +186,77 @@ --- +## 2-2. 대외 접점 3-트랙 재구성 (visitor / business / agency) — v3.2 + +> **소유자 확정(2026-07-12)**: 대외 접점을 **visitor(관람객) / business(비즈니스=주최자·참가업체) / agency(에이전시=공사·장치·협력사)** 3개 트랙으로 나눠 분리한다. 근거 = `docs/analysis/coex-website.md` — 코엑스가 방문자 유형별로 **사이트(도메인) 자체를 3개(VISITOR `coex.co.kr` / BUSINESS `business.coex.co.kr` / CYBER 참가신청 `cybercoex.co.kr`)로 분리**한 IA를 킨텍스 도메인에 이식한다. +> +> **보존 원칙**: 본 절은 §2 페르소나·§2-1 역할별 포털 매트릭스·§2-1-1 계정 체계·M1~M18·§8 아키텍처를 **삭제·재작성하지 않는다.** 6역할/7페르소나 구조는 유지되고, 그 위에 "대외 접점을 3개 트랙으로 묶어 진입점·서브홈·네비게이션 IA를 재편하는" **트랙 셸 레이어**만 순증한다. 내부 전용 역할(킨텍스 직원 ops·테넌트/플랫폼 관리자 admin)은 대외 트랙이 아니므로 3-트랙 밖에 그대로 둔다. + +### 2-2-1. 3-트랙 정의 — 대상·핵심 여정·진입 화면·제공 기능 + +| 트랙 | 대상(§2 역할 매핑) | 코엑스 대응 | 핵심 여정 | 진입 화면 | 제공 기능(모듈·SCR) | +|---|---|---|---|---|---| +| **visitor** (관람객) | 관람객 + 일반 대중(Public) | VISITOR `coex.co.kr` + 가이드 | 행사 탐색 → 사전등록/티켓 → 방문(교통·주차·길찾기) → 배지·체크인 → 관람·매칭 → 재방문 | visitor 서브홈(공개 랜딩) → SCR-P1 | 공개 홍보 사이트 M12(SCR-P1·P2·P3·P5), 사전등록·티켓 M10(SCR-P4·P6·P7·P8), wayfinding M13, 비즈매칭 M11, 관람객 앱(SCR-M5~M9·M14·M15) | +| **business** (비즈니스) | 주최자(Organizer) + 참가업체(Exhibitor) | BUSINESS `business.coex.co.kr` + CYBER `cybercoex.co.kr` | (주최자) 홀배정·견적 → 배치·서류 → 옥션 발주 → 정산·BI / (참가업체) 부스 신청 → 설계·유틸리티 → 시각화 → 리드 | business 서브홈 → 로그인 → 역할별 홈(주최자 SCR-02 / 참가 SCR-05) | 홀배정·견적 M1, 배치 M2, 부스설계 M3, 유틸리티 M4, 시각화 M5, 서류·마일스톤 M6, 옥션 발주 M15, 정산 M9, 관람·리드 M10, BI M16 | +| **agency** (에이전시) | 장치·공사업체(Contractor) + 등록·협력업체 | BUSINESS 하위 **서비스협력업체** + 안전경영 **온라인작업신고** (킨텍스는 독립 트랙으로 승격) | 등록업체 검증 → AI 설계자료 열람 → **옥션 응찰(견적서 제출)** → 수주 → 도면 제출·규정검증 → 현장 시공·작업신고 | agency 서브홈 → 로그인 → 수주/응찰 대시보드(SCR-27/28) | 부스설계(공유) M3, 규정검증 M3(SCR-09), 옥션 응찰 M15(SCR-27·28), 등록업체 매칭 M7(SCR-38), 반입/작업신고 M8, 현장 앱(SCR-M1·M10) | + +- **트랙 ↔ 역할 관계**: 트랙은 역할의 **상위 묶음(진입점 그룹)** 이지 역할의 대체가 아니다. business 트랙 안에 organizer·exhibitor 2역할이 공존하고, agency 트랙 안에 contractor + 등록업체 계정이 공존한다. 로그인 후 실제 권한·화면은 기존 §2 역할 RBAC 그대로. +- **코엑스와의 차이(정당화)**: 코엑스는 agency(협력사)를 BUSINESS 하위로 흡수했으나, 킨텍스는 **독립부스 등록 장치업체 필수·미등록 시공 엄금·리깅 구조계산서·739개 등록업체 DB·M15 역경매 옥션**이라는 강한 도메인이 있어 agency를 **독립 트랙**으로 세운다(§4 대비표 근거). + +### 2-2-2. 코엑스에서 차용할 요소 (트랙별) + +| 트랙 | 코엑스 차용 요소 | 킨텍스 반영 | +|---|---|---| +| visitor | "가이드" 단일 허브(오시는 길·주차·실내 길찾기·VR·편의시설·알림마당·문의) + 관심분야 맞춤 알림 + 수어/접근성 전면 노출 | visitor 서브홈에 방문 가이드 허브 구성(교통 GTX-A·주차 iparking·wayfinding M13·편의시설), 맞춤 알림·접근성 고지(M12·M10) | +| business | 임대절차→시설규격→요금→서류/도면 **단계별 실무 흐름** + 참가업체 신청 **공통 플랫폼(cybercoex)** 일원화 | business 서브홈에 주최자(대관·M1)·참가업체(신청·M3/M4) 단계 안내 + 킨텍스 최대 공백인 **참가업체 공통 e-서비스**를 business 트랙으로 통합 | +| agency | 서비스협력업체 리스트 + 안전경영 온라인작업신고 통합 | agency 서브홈에 등록업체 검증·수주·옥션·도면제출·작업신고(kxwp 릴레이)를 하나로(코엑스보다 강한 독립 트랙) | + +### 2-2-3. 공개 사이트 구조 — 랜딩 3-분기 + 트랙별 서브홈 + 로그인 후 홈 + +**(A) 랜딩(루트) = 3-트랙 분기 관문.** 최상위 진입점(예: `www.` 또는 테넌트 루트)은 코엑스 스타일로 **visitor / business / agency 3개 카드로 명확히 분기**하는 관문 랜딩을 제공한다. 관람객이 절대다수이므로 visitor를 시각적 1순위(히어로·행사 카드)로 두고, business·agency는 상단 유틸리티/카드로 노출(코엑스가 VISITOR를 메인에 두고 BUSINESS를 링크로 분리한 패턴 차용). + +**(B) 트랙별 서브홈(전용 공개 홈 3개).** +- **visitor 서브홈** — 공개·비로그인. 행사 일정·히어로·사전등록/티켓 CTA·방문 가이드 허브(SCR-P1 확장). SEO·다국어·MDI 비적용(§8-1). +- **business 서브홈** — 공개(안내) + 로그인 유도. 주최자 대관 안내·참가업체 참가 안내·요금·서류 안내(SCR-P6 확장) → "로그인/신청" CTA. +- **agency 서브홈** — 공개(안내) + 등록업체 로그인. 등록업체 안내·진행 중 옥션 공고·작업신고 안내 → 등록업체 로그인 CTA. + +**(C) 로그인 후 랜딩 — 권고: "트랙-스코프 홈(Track-scoped Home)".** +로그인 후 홈은 **단일 범용 홈(역할별 변형)** vs **트랙별 별도 홈** 두 안 중, **트랙별 별도 홈(단, 트랙 내부는 역할 변형)** 을 권고한다. + +| 안 | 내용 | 장점 | 단점 | 판정 | +|---|---|---|---|---| +| 단일 범용 홈(역할별 위젯 변형) | 로그인 후 하나의 홈, 역할에 따라 위젯만 다름 | 구현 단순, 계정 승격 연속성(§2-1-1) 매끄러움 | 트랙 정체성 약함, business·agency·visitor 혼재로 IA 혼란 | 부분 채택(트랙 내부) | +| **트랙별 별도 홈(트랙 내 역할 변형)** | 트랙 셸마다 홈, 홈 안에서 역할(주최자/참가 · 시공/등록)로 위젯 변형 | 코엑스식 트랙 정체성·최소권한·공격면 축소(§2-1), 기존 SCR-02/05/27 재사용 | 홈 3벌 유지 | **권고** | + +- **권고 근거**: business 트랙은 organizer(SCR-02)·exhibitor(SCR-05) **기존 홈을 그대로** 트랙 내 역할 변형으로 재사용하고, agency는 수주/응찰 대시보드(SCR-27/28)를 홈으로 삼는다 → **신규 홈 화면 최소**(트랙 관문 랜딩 + 서브홈 3개만 신규, 나머지는 재배치). 계정 승격 연속성(§2-1-1)은 **단일 통합 계정** 위에서 유지되므로 트랙별 홈이어도 데이터 연속성은 훼손되지 않는다(관람객→바이어/참가 승격 시 business 트랙 접근 권한만 추가). + +### 2-2-4. 라우트 체계 — 마이그레이션 비용 비교 후 권고 + +| 안 | 라우트 | 마이그레이션 비용 | SEO/딥링크 | 판정 | +|---|---|---|---|---| +| A. 전면 트랙 프리픽스 | 기존 `/o/`·`/e/`·`/c/`·`/tickets/`를 `/business/o/`·`/business/e/`·`/agency/c/`·`/visitor/tickets/`로 재작성 | **높음** — 전 딥링크·MDI 세션키(§design 2.7 `kintex.mdi.{role}.{eventId}`)·티켓 공개 라우트(`/tickets/:orderNo`) SEO 인덱스 전면 변경, 리다이렉트 맵 필요 | 기존 인덱스 무효화 위험 | 미채택 | +| **B. 트랙 셸 레이어 + 기존 딥 라우트 유지(하이브리드)** | **신규 얕은 트랙 진입 라우트만 추가** — `/`(관문 랜딩), `/visitor`(서브홈), `/business`(서브홈), `/agency`(서브홈). 로그인 후 **기존 역할 딥 라우트(`/o/{eventId}/...`·`/e/{eventId}/...`·`/m/...`·`/gallery/...`·`/tickets/...`)는 그대로 유지** | **낮음** — 기존 화면·MDI·티켓 SEO·세션키 불변, 트랙은 상위 셸/네비로만 그룹핑 | 기존 인덱스 보존, 신규 트랙 랜딩만 인덱싱 | **권고** | +| C. 서브도메인 분리 | `visit.` / `business.` / `agency.` 서브도메인(코엑스식) | 중간 — 배포·인증서·SSO 쿠키 도메인 조정, 단 §2-1·§8-1이 이미 역할 서브도메인(organizer.·exhibitor.·contractor.) 전제 | 트랙별 브랜딩·격리 명확 | **선택적 상위 옵션**(운영 단계) | + +- **권고 = 안 B(하이브리드) + 안 C 선택 결합**: 1차는 **경로 기반 트랙 셸(안 B)** 로 마이그레이션 비용 없이 트랙 IA를 얹고, 기존 딥 라우트(`/o/`·`/e/`·`/m/`·`/tickets/`)와 MDI 셸(design §2.7)·티켓 공개 라우트(SCR-P7/P8)를 **불변**으로 둔다. 운영 확장 시 §2-1의 역할 서브도메인 전략과 정합하여 트랙 서브도메인(안 C)을 상위에 얹을 수 있다(예: `business.` → business 서브홈 → 내부적으로 organizer/exhibitor 앱). +- **트랙 ↔ 기존 서브도메인 매핑**(§2-1 보존): visitor 트랙 ⊇ {`www/expo.` 공개 + 관람객 앱}, business 트랙 ⊇ {`organizer.`·`exhibitor.`}, agency 트랙 ⊇ {`contractor.`}. ops·admin 서브도메인은 트랙 외부(내부 전용). + +### 2-2-5. 기존 화면 재배치 매핑표 (현행 SCR/라우트 → 트랙) + +> 원칙: **화면·라우트는 이동·재작성하지 않는다**(안 B). 아래는 각 화면이 **어느 트랙 셸의 네비게이션·진입 그룹에 속하는가**의 논리적 귀속 표이며, designer/frontend는 이를 트랙 서브홈·네비 구성에만 사용한다. + +| 트랙 | 귀속 화면(design.md SCR) | 현행 라우트(유지) | 신규(트랙 셸) | +|---|---|---|---| +| **관문 랜딩** | (신규) 3-트랙 분기 관문 | `/` | ★신규 SCR 필요(designer) | +| **visitor** | SCR-P1·P2·P3·P5(공개사이트), SCR-P4·P6(등록·문의), SCR-P7·P8(티켓), SCR-M5~M9·M14·M15(관람객 앱) | `www/expo.` 공개, `/tickets/*`, 관람객 앱 | ★visitor 서브홈(SCR-P1 확장) | +| **business** | SCR-01(로그인), SCR-02·03·04·19(주최자), SCR-05·06·07·08·12(참가), SCR-15·18·20·21·22·23·24·25·26·29(M1/M6/M8/M9/M15 발주), SCR-13(BI), SCR-30·31·32(관람·리드), SCR-39~48(공통업무) | `/o/{eventId}/*`, `/e/{eventId}/*`, `/gallery/*` | ★business 서브홈(SCR-P6 확장) | +| **agency** | SCR-06·09(설계·규정, 공유), SCR-27·28(옥션 응찰), SCR-38(등록업체), SCR-M1·M10(현장·통행증) | `/c/{eventId}/*`(contractor, 기존 exhibitor 포털 공유 라우트), 옥션 응찰 라우트 | ★agency 서브홈(등록업체·옥션 공고) | +| **트랙 외부(내부)** | SCR-10·11(홀매니저), SCR-14(현장운영), SCR-16·A1~A10(관리자·시스템관리) | `/m/{eventId}/*`, `admin.` | (트랙 재편 대상 아님, 보존) | + +- **신규 화면 = 4종만**(관문 랜딩 1 + 서브홈 3). 나머지는 전량 기존 SCR 재사용 → designer/frontend 작업량 최소(§구현 지시서 `_workspace/plan_3track.md`). + +--- + ## 3. 현행(As-Is) 프로세스 분석 ### 3-1. 주최자 타임라인과 병목 @@ -1017,4 +1091,5 @@ graph TB | v1.2 | 2026-07-11 | planner | **기술 스택 확정 — React + Spring Boot 3.x(Java 17) + MyBatis + PostgreSQL(PostGIS), 나노바나나 Python 워커 사이드카. GUARDiA 표준 프레임워크 정렬(사용자 지정).** §8 아키텍처 전면 정합화: 백엔드 FastAPI→Spring Boot 3.x + MyBatis(REST + WebSocket/STOMP, 룰·배치/배선 엔진=서비스 계층 + PostGIS 공간 SQL), 프론트 Next.js→React 18/19(Vite·TS, SVG/WebGL 캔버스), 비동기 큐 Redis 유지 + 이미지 생성은 별도 **Python 워커 사이드카(`tools/nanobanana`, google-genai Python SDK)** 로 분리(Spring이 RenderJob 큐잉→Python 워커 소비·생성→오브젝트 스토리지 적재→WebSocket 완료 푸시, 서류·알림도 동일 큐). Python 워커 유지 근거 명시(ReRoomAI 검증 client.py·Python SDK — Java 재구현 회피). 인증(행사 단위 RBAC+JWT)·오브젝트 스토리지 유지. §8 mermaid 갱신. **기능 범위(M1~M9)·우선순위·나노바나나 파이프라인 로직 불변** — 스택 표기 정합화만 수행 | | **v2.0** | 2026-07-11 | planner | **정체성 확장 — 킨텍스 자동전시시스템(Exhibition Automation Platform).** 글로벌 전시테크 크롤링(Eventleaf·VenueSight·Whova·ExpoPlatform·Eventbase·Pointr·Swapcard·Brella·Grip·RainFocus·ExhibitForce·FindRFP·Procore·4castplus) 근거로 확장. ①§1 비전 재정의(생애주기 폐루프, M15 옥션이 코어를 발주로 연결) ②§2 역할·포털 매트릭스 신설 — 6역할(주최자·참가·업체·홀매니저·관리자·관람객/대중) 웹/모바일 분리(organizer·exhibitor·contractor·ops·admin·public+visitor), 관리자·일반대중 페르소나 추가 ③§4 모듈맵 mermaid 확장(M10~M18) + 우선순위 총괄 ④§5A 신규 모듈 상세: **M15 공사/장치 옥션(P1·핵심, 역경매·견적서(Quotation)=응찰·실시간 순위·종합평가 낙찰·등록업체만 응찰·Auction 1─N Quotation ─ Award·PDF/버전, 입찰 플로우 시퀀스 다이어그램)**, M10 관람객 등록·배지·리드캡처(P1), M12 마케팅·EDM·공개 홍보 사이트(P1·SEO/다국어), M16 경영분석 BI(P2→**P1 승격**, design.md 반영은 designer 후속), M17 CMS(P1), M18 관리자 백오피스(P1), M11 비즈매칭·M13 wayfinding·M14 현장운영(P2) ⑤**M2·M3 3안 생성→선택/병합 UX 구체화**(1·2·3안 다양화, 구역/블록 병합, 병합 후 규정 재검증, 버전 기록) ⑥§7-3 엔티티 확장(Auction/Quotation/Award·Visitor/Badge/Lead·KPI/Content/User) ⑦§8-1 아키텍처 보강(역할별 분리 프론트+SSO/RBAC+공개사이트 SEO/다국어+백오피스+옥션 엔진) ⑧**§5B 공통/시스템관리 레이어(UIWS 표준 이식) 신설** — kintex 스택=UIWS(GUARDiA 표준 프레임워크) 동일 → 시스템관리(사용자·RBAC·공통코드·메뉴·감사로그·시스템설정)와 공통 업무기능(worklog·schedule·message·stats·notice·opinion·search·meeting·report·notification·audit) + 인증(JWT + **2차 인증 OTP TOTP RFC6238** + 로그인 실패 잠금 + admin 비번 env `ADMIN_PASSWORD_ENC` 주입)을 `workspace/uiws` 레퍼런스로 이식, 도메인 모듈은 그 위에 적재. **M18 관리자 시스템을 UIWS 시스템관리와 통합(중복 제거)**, BI/CMS/알림 경계 규칙 정의, Phase 1 선행 기반으로 로드맵 반영. ⑨**§5A M16-1 운영사(킨텍스·venue operator) 관점 수익성/ROI 소절 신설** — 참가업체 관점 ROI(리드 기반)와 명시 구분하고, 킨텍스 관점 7지표(홀·기간별 가동률/매출구성/행사별 P&L·마진/전시장별 ROI·RevPAD·㎡당 수익/참가사 리텐션·LTV/수요예측·수율·가격 최적화/경영진 KPI) + 데이터원(M1·M4·M9·M10·M15) + **BI 데이터마트(스타 스키마 Fact/Dim, DA 후속 트랙)** 정의. **기존 M2~M5 P0 코어·§6 나노바나나 로직·§8 확정 스택 보존.** design.md/타 문서는 미수정 — designer/planner/DA 후속 반영 필요로 표기 | | **v3.0** | 2026-07-11 | planner | **멀티테넌시(다중 전시관 SaaS) 확장 — 킨텍스 전용 → 다중 전시관, KINTEX=기준 테넌트 #1.** 기존 스코프(부스 코어 M2~M5·도메인 M10~M18·§5B 공통 레이어·§6 나노바나나·§8 확정 스택) **전부 보존**, 격리 레이어만 순증. ①헤더 v3.0 정체성 확장(다중 전시관 SaaS) ②**§1A 멀티테넌시 절 신설** — 테넌트=전시관(Venue) 모델(tenant_code·명칭·branding·domain/subdomain·active·locale, 홀·요율·규정 룰셋·부스표준을 테넌트 소유로 재정의)·`tenant_id` 전파 및 격리(전 도메인 엔티티 격리 vs 전역/테넌트 참조 구분)·테넌트 컨텍스트 해소(서브도메인 kintex/coex.wise.ai.kr 우선 + 사용자 소속 보조, fail-closed 주입)·역할 계층(플랫폼 슈퍼관리자 vs 테넌트 관리자 2계층, 행사 RBAC는 테넌트 내부 스코프)·마이그레이션(기존 데이터 tenant_id=1 백필, DDL은 db-engineer/DA 후속) ③**§2 역할 갱신** — 페르소나 관리자 행을 테넌트 관리자로 재정의 + 플랫폼 슈퍼관리자 신규, 권한 모델을 "테넌트 격리 ⊃ 행사 RBAC" 3중 구조로, §2-1 포털 매트릭스 admin 2계층 분리 ④**§7 데이터모델 갱신** — §7-1 마스터데이터 테넌트 스코프 재정의(킨텍스 실측=테넌트#1 시드), §7-3 Tenant/Venue 엔티티·tenant_id 전파·참조 구분·역할 계층·백필 추가 ⑤**§8-2 멀티테넌트 격리 전략 신설** — 공유 스키마 + tenant_id 컬럼(단일 kintex_db 유지·DB/스키마 분리 미채택, 비교표)·fail-closed 다층 강제(필터→서비스가드→MyBatis 공통 인터셉터→PostGIS)·성능(`(tenant_id,…)` 선두 인덱스)·보안(교차 차단·감사·스토리지/쿼터 격리)·온보딩 6단(코드 배포 없이 데이터 온보딩) ⑥§1 Non-Goal에 온보딩 범위 한정 추가. **design.md·architecture/*.md·src 미수정** — db-engineer/DA/designer 후속 반영 필요로 표기. 근거 없는 코엑스 실측 추정 배제(온보딩 시 입력) | +| **v3.2** | 2026-07-12 | planner | **제품 명칭 확정 + 대외 접점 3-트랙 재구성(소유자 확정 2026-07-12).** 기존 스코프(M1~M18·§1A 멀티테넌시·§2 6역할/7페르소나·§2-1 포털 매트릭스·§5B 공통레이어·§6 나노바나나·§8 아키텍처·design.md SCR-*) **전부 보존**, IA 레이어만 순증. ①**제품 공식 명칭 = "KINTEX AI 전시·행사시스템"**(기존 "자동전시시스템/Exhibition Automation Platform" 대체 — 전시+행사/이벤트 포괄) → H1 제목·헤더 명칭 절 갱신, 정본 선언(기존 표기는 문맥 보존상 잔존) ②**`docs/analysis/coex-website.md` 신설** — 코엑스 3-사이트 IA(VISITOR `coex.co.kr`/BUSINESS `business.coex.co.kr`/CYBER 참가신청 `cybercoex.co.kr`) 분석 + 킨텍스(kintex.com) 대비표 11축 + 차용 요소. WebFetch 3사이트 + WebSearch 보조 ③**§2-2 대외 접점 3-트랙 재구성 신설** — visitor(관람객)/business(주최자·참가업체)/agency(공사·장치·협력사) 3-트랙 정의(대상·여정·진입화면·기능 매핑), 코엑스 차용요소, 공개사이트 구조(관문 랜딩 3-분기 + 트랙별 서브홈 3 + **로그인 후 트랙-스코프 홈 권고**), **라우트 체계 3안 비교→하이브리드(트랙 셸 + 기존 딥라우트 유지, 마이그레이션 비용 최소) 권고**, 기존 SCR/라우트→트랙 재배치 매핑표(신규 화면 4종=관문+서브홈3만, 나머지 재사용). 트랙은 역할의 상위 묶음(대체 아님), 내부역할 ops·admin은 트랙 외부 유지. 헤더 v3.2 정체성 라인 추가. **design.md·src 미수정(designer/frontend 후속)** — 구현 지시서 `_workspace/plan_3track.md` 별도 작성 | | **v3.1** | 2026-07-11 | planner | **계정 통합 + 가입 트랙 분리 · 모바일 2타깃 확정(소유자 확정 2026-07-11).** 기존 스코프 전부 보존, 계정·앱 채널 전략만 정밀화(상충 시 확정안 우선·삭제 없이 개정 표기). ①**§2-1 채널 매트릭스 개정** — 모바일 열을 운영 앱(B2B)/관람객 앱(B2C)으로 분리, 가입 트랙 열 신설(업무=승인·초대+2FA 필수 vs 관람객=간편가입/게스트 예매+2FA 미강제) ②**§2-1-1 신설** — (A)계정 체계 단일 통합+가입 트랙 분리(승격 시 단일 계정 등급 상향으로 리드·비즈매칭·재방문 이력 연속성 유지), (B)모바일 코드베이스 1개(Expo `mobile/`)·배포 타깃 2개(운영 앱=스토어 미공개 사내 QR/APK, 관람객 앱=스토어 공개), 관람객 1차 접점=공개 웹(SCR-P7/P8)·앱=리텐션 채널 ③**§5B-3 인증 정밀화** — 2FA 대상을 "업무 사용자 필수·관람객 미강제"로, 승격 시 2FA 필수 전환 명시 ④**M10 갱신** — 간편가입/게스트 예매(SCR-P7)·계정 승격 연속성·게스트 예매 개인정보/병합 정책 반영. 근거: `docs/analysis/ticketing-app-benchmark.md`(게스트 예매·간편가입 업계 표준). design.md·타 문서 미수정(designer 후속 반영 필요), 시크릿 미기재 | diff --git a/docs/WORK_STATUS.md b/docs/WORK_STATUS.md index 53d5438..d98ef38 100644 --- a/docs/WORK_STATUS.md +++ b/docs/WORK_STATUS.md @@ -99,6 +99,7 @@ | 2026-07-12 | **Stitch 전 화면 확보 완료(64/64)** — 서비스 회복 후 수확 패스 재실행: 잔여 39화면 전부 서버측 지연 생성 완료 상태(프로젝트 27→155 화면)로 재생성 0회·다운로드 43파일(보조 변형 5 포함: P4 3단계·P7 예매확인·M15 권종선택) 실패 0. `_workspace/stitch_gen/{harvest2.py,screen_titles.txt,harvest_report.md}`. 다음: frontend/mobile dev 이식 + design.md 🔲미생성 마커 갱신(designer 경유) | | 2026-07-12 | **실데이터·2FA 트랙 마감** — ①실데이터 집계 API 5패키지(analytics·dashboard·ops·admin·catalog + V13 인덱스) ②TOTP 2FA 완결(SecretCipher AES-256-GCM·V12·OtpChallengePanel/OtpSetupPage·OTP_ENFORCE env) ③공통 업무기능 SCR-39~48 화면(`screens/work/`) 배선 ④M2 부스 겹침 검사(BOOTH_OVERLAP·compliance-v1.1) + 단위테스트 3종. 검증: backend compileJava+test·frontend tsc 통과, QA PASS(blocker/major 0, minor 2=RIGGING_RANGE semantics 소유자 결정 대기·운영 KINTEX_OTP_ENC_KEY 주입 게이트 — `_workspace/09_qa_track_close.md`). 계약 갭 기록: `_workspace/{07_work_api_gaps,08_m2m5_contract_changes}.md` | | 2026-07-12 | **Stitch 확보 화면 이식 완료(웹 24 + 공개 7단계플로우 + 모바일 1)** — 에이전트 7팀 병렬(폴더 소유권 분리·공유파일 통합자 단일 배선). ①도메인: SCR-22/23/25(서류·신고서류·도크, M6/M8 샘플)·SCR-26/27/29/38(옥션 3종+수주 대시보드, M15 샘플, 봉인입찰 마스킹·등록업체만 응찰 UI)·SCR-30/32/33/34(관람객·리드·EDM·스폰서십, M10/M12 샘플, PII 마스킹)·SCR-35/36/37(CMS 3종, M17 샘플) ②관리자: **A5 감사로그·A6 시스템설정 = 라이브 백엔드 실배선**(PageResponse·시크릿 마스킹), A8 룰셋(정적 v1.1 스냅샷)·A9 테넌트(샘플) ③공개: P1~P7 자체 PublicShell(비인증 /public/*·/tickets/*, PG위임 고지) ④모바일: M15 티켓지갑(mobile/app/tickets, QR placeholder) ⑤통합: App 라우트 18종+AppShell "도메인 모듈" 네비. tsc -b EXIT 0·QA PASS(minor 2 코스메틱: kx-field 접두, ★/✓ 글리프). 각 팀 API 계약 초안 = `_workspace/port_*.md`. 커밋 becbc55 | +| 2026-07-12 | **10~12차 웨이브 + 리뉴얼 1차 체크포인트** — ①W10 이메일 채널(자체 Postfix 로컬 제출 — 소유자 승인·env 프로비저닝: 옥션 개설 공사업체 인앱+이메일 통지·EDM 발송(수신동의·상한500)·비번 재설정 메일·mail_log V36) ②W11 WISE 셸 정렬(소유자 지적 9건: 햄버거·단일펼침 아코디언·6그룹 IA 재구성·시스템관리 그룹·KINTEX CI 워드마크 로고·홈 차트 3종·하단 반응형·캘린더 정합·goScoped 링크수정(/login 폴백 제거·홀 파싱)) ③W12 시스템관리 기본기 8종(UIWS 40+ 대비 누락 지적 — 조직dept/company·프로그램·역할메뉴맵·인증정책·로그인이력·오류로그·시스템상태·메일/알림설정, V37·라우트 10종) ④제품 아이덴티티(지적 "뭐하는 사이트인지 모르겠다" — 공개 랜딩 제품 히어로+역할카드4+AI 파이프라인 스텝·로그인 태그라인·루트 분기 미인증→/public) ⑤홈 AI 허브(지적 "AI가 어디 있냐" — AI 도구 카드 5+자연어 퀵 입력) ⑥메뉴 IA 정합(누락 13종 편입·시스템관리 5소그룹·dead 0 — kintex-menu-recompose 절차) ⑦모바일 QR 페이지(/app-qr — WISE AppQrCode, EAS G3 승인·빌드 진행) ⑧제품명 확정 "KINTEX AI 전시·행사시스템"(4개 로케일 스윕) ⑨V38 데모 폐루프 시드(공통코드30·프로그램75·부서15·회사16·부스12·리드15·결재5·청구8·데모계정4 — 홈 todos/KPI 활성) ⑩SPA 캐시 정책(index.html no-store — 배포 반영 즉시). **신규 하네스 3종**: wise-ui 정렬(+menu-ia)·전면 리뉴얼(testdata)·벤치마킹(analyst·crawler). COEX 분석→3-트랙(visitor/business/agency) 기획 완료(PLANNING v3.2·신규 4화면 Stitch 진행) | | 2026-07-12 | **8·9차 웨이브(100대 기능 8종) + ★SCR-HOME 메인 홈 + 테넌트 표준 + 크롤 적재** — ①**SCR-HOME**(소유자 지시: 홈 없음 지적→design.md v2.1.2 확정판·Stitch 시안(프로젝트 정리 후 생성 성공, scr_home/) 정합): `/home` 랜딩(로그인→홈 전환·워크스페이스 선택 흡수)=역할별 KPI+배너 캐러셀+**전시 포스터 쇼케이스**+WISE 월캘린더(홀센터 동적 필터)+**역할별 내 할 일**+공지/빠른작업/활동+워크스페이스 그리드+ShellFooter+`/api/home/{todos,showcase,hall-centers,summary}` ②**테넌트 표준(소유자 지시)**: ten_id='KINTEX'(V31 재명명·코드 정규화·JWT 하위호환)+**tenant_id 선두 복합 PK**(V31 전환+V27/29/30/33/34/35 신규분 표준 적용) ③크롤: kintex.com 전시 34건+포스터+상세(주최·홈페이지·품목·소개, V32) ④W8: F100 AI라우터(Claude→Ollama 폴백·AiConfig)+F051 리드AI재계산+CMS AI번역 실배선·F005/6 부스판매(V27·원자 hold)·F035 BOQ+F084 옥션수수료 정산(V28)·F028 전자결재(V29·결재함 실배선·/work/approval) ⑤W9: F041/42/43 물류4탭(V33)·F085 환불룰(refund-v1.0)+F083 세금계산서·리포트(V34·G2 게이트)·F092 Text-to-SQL(7단계 가드·PII차단)+F025 규정챗봇·F099 웹훅(HMAC 인바운드·아웃바운드 스텁)+F052 팔로업EDM 트리거(V35). 검증: compileJava·test·tsc·vite 전부 EXIT 0. 잔여 게이트: PG/국세청/실발송(G2)·공사업체 통지 이메일(Postfix 승인 대기) | | 2026-07-12 | **7차 웨이브(MDI+테넌시2단계+i18n 스윕2)** — ①MDI 셸: 탭 문서 바(`MdiTabBar`+`mdiStore` sessionStorage·라우트 동기화·dedup·MAX 10·키보드 접근성·다크 토큰) 순증 레이어 — 잔여: DocumentHost 상태 보존(§2.7-3)·드래그 재정렬 ②테넌시 2단계: JWT `tid` 클레임(하위호환 폴백)·`EventAccessGuard` 테넌트 fail-closed(교차 테넌트 403 — `EventTenantMapper`+격리 테스트 3종)·전역 집계(analytics/admin/sysuser) 명시 스코핑 — company·audit_log는 Phase 3 후보 ③i18n 스윕2: 코어+admin 17화면·네임스페이스 30종(4개 언어) — 잔여 P2(도메인 모듈·work 공통)·P3(공유 ui) 목록=_workspace/impl_i18n_sweep2.md. 검증: tsc·vite·compileJava·test(75개) 전부 EXIT 0 | | 2026-07-12 | **5·6차 웨이브(NFR+멀티테넌시) + 운영 도메인 라이브** — ①W5-1 다크테마(global.css `--dk-*`→`[data-theme=dark]` remap·시스템 선호 폴백·themeStore(localStorage)·AppShell 토글·공유 CSS 하드코딩 hex 토큰화·focus-ring/reduced-motion/스킵링크) ②W5-2 i18n(react-i18next ko/en/zh/ja·공개 P1~P7+로그인/가입/비번찾기 전 문구·LanguageSwitcher(공개셸+로그인+AppShell 배선)·fallback ko) ③W6 멀티테넌시 1단계(V26 tenant 마스터+event/hall/app_user tenant_id 순증·TenantContextFilter(X-Tenant-Id→Host→kintex)·catalog/hall 스코핑·`/api/admin/tenants` GET/POST 실배선 — 회귀 0) ④**운영 도메인 https://kintex.wise.ai.kr 라이브**(위 §2 참조). 검증: tsc·vite·compileJava·test 전부 EXIT 0 | diff --git a/docs/analysis/coex-website.md b/docs/analysis/coex-website.md new file mode 100644 index 0000000..7bc3fe1 --- /dev/null +++ b/docs/analysis/coex-website.md @@ -0,0 +1,134 @@ +# 코엑스(COEX) 웹사이트 분석 + +> 분석일: 2026-07-12 · 대상: https://www.coex.co.kr/ (VISITOR), https://business.coex.co.kr/ (BUSINESS), cybercoex.co.kr / exhibitor.cybercoex.co.kr (참가업체 온라인신청) +> 목적: 코엑스의 방문자 유형별 정보구조(IA) 분석 → 킨텍스 자동전시시스템 **대외 접점 3-트랙(visitor/business/agency) 재구성** 근거 확보 (PLANNING §2-2) +> 방법: WebFetch(3 사이트 IA 크롤) + WebSearch 보조. 로그인·신청 상세는 접근 불가로 검색 결과로 보강. + +--- + +## 0. 핵심 발견 — 코엑스는 방문자 유형별로 "사이트 자체"를 3개로 분리한다 + +코엑스 IA의 결정적 특징은 **메뉴 분기가 아니라 사이트(도메인) 분기**라는 점이다. 킨텍스가 단일 사이트(kintex.com) 안에서 정보·서식을 제공하는 것과 대비된다. + +| 사이트 | 도메인 | 1차 대상 | 성격 | +|---|---|---|---| +| **VISITOR** | `www.coex.co.kr` | 관람객·일반 대중 | 방문 전/중 편의·행사 탐색 (마케팅·안내 톤) | +| **BUSINESS** | `business.coex.co.kr` | 전시주최자·임차인·(협력사) | 대관·임대·시설 규격·협력사·안전 (B2B 실무 톤) | +| **CYBER(참가신청)** | `cybercoex.co.kr` / `exhibitor.cybercoex.co.kr` | 참가업체 | 부스+부대시설 온라인 신청·결제 (트랜잭션 톤) | + +이 3분할은 소유자가 지시한 **visitor / business / agency** 3-트랙과 거의 1:1로 대응한다(§4 대비표). 즉 코엑스는 이미 "누가 오느냐"로 진입점을 물리적으로 갈라 놓았고, 이는 킨텍스 시스템 재구성의 실증 레퍼런스가 된다. + +--- + +## 1. VISITOR 사이트 (www.coex.co.kr) — 관람객·일반 대중 + +### 1-1. GNB 구조 +- **40th Anniversary** — 창립 40주년 캠페인(브랜드 히어로) +- **행사** — 전시/컨퍼런스 일정 (진행중 30개 카드형, 티켓오픈 3개 하이라이트, Convention/Exhibition 카테고리, 일정·홈페이지·예약링크) +- **가이드(Guide)** — 방문객 편의 정보(§1-2) +- **하이라이트** — 주요 콘텐츠/기획 +- **안전경영** — 경영방침·신고(공용) +- **Coex 소개** — 회사정보·채용·MICE 클러스터 +- **Business** — 외부 링크(business.coex.co.kr로 이탈) +- **마곡 컨벤션센터** — 별도 시설 링크 + +### 1-2. 가이드(Guide) — 방문객 여정의 핵심 +| 하위 메뉴 | 제공 정보 | 방문 시점 | +|---|---|---| +| **오시는 길** | 지하철(2/7/9호선)·버스 6개 정류장·승용차 7개 경로·자전거 등 교통수단별 상세 | 방문 전 | +| **주차안내** | 옥상·지하주차장 진입로, 건물별 게이트, 요금·위치 | 방문 전 | +| **편의시설** | 층별 편의 서비스(식음·쇼핑·시설) | 방문 전/중 | +| **실내 길찾기(실내 네비게이션)** | 광활한 코엑스 내부 목적지 탐색(wayfinding) | 방문 중 | +| **Coex VR** | 가상현실 사전 답사/현장 활용 | 방문 전/중 | +| **알림마당** | 공지사항·입찰공고 | 조회 | +| **고객문의** | 문의 접수 | 조회 | +| **뉴스** | 최신 소식 | 조회 | + +- **접근성**: "수어 통역 서비스 제공" 명시 — 접근성을 방문안내 전면에 노출. +- **맞춤 알림**: 관심분야 선택 후 휴대폰 기반 맞춤 알림(관람객 리텐션 장치). + +### 1-3. Family Site / 커머스 연계 +CoexMall(쇼핑몰), KITA, WTC Seoul, KTNET, CALT, Coex VINA, COEX STORE 등 — 전시장을 넘어선 복합 MICE·리테일 생태계 링크. + +--- + +## 2. BUSINESS 사이트 (business.coex.co.kr) — 주최자·임차인·협력사 + +### 2-1. GNB 구조 +| 최상위 | 하위 | +|---|---| +| **전시/컨벤션** | 사업소개·주최전시회(26개 참가사 모집중)·컨벤션·해외사업(베트남·인니 등 8개) | +| **전시장** | 시설안내·임대절차및상담·임대관련자료(신청서및신고서/안내자료/도면)·임대비용·**서비스협력업체** | +| **회의실** | 시설안내·임대절차·임대관련자료·코엑스 스토어·**서비스협력업체** | +| **광장/로비** | 시설안내·이용절차·이용관련자료 | +| **베뉴서비스** | 이벤트·F&B·광고·촬영 | +| **가이드** | 주차·편의시설·고객문의·VR투어 (VISITOR 가이드 재노출) | +| **안전경영** | 경영방침·목표·실천강령·**온라인작업신고** | +| **Coex 소개** | 회사정보·연혁·조직도·채용·**MICE클러스터** | + +### 2-2. 대상별 정보 배치 (BUSINESS 사이트 내부에서 다시 3자 구분) +- **전시주최자/임차인**: 전시장 > 임대절차및상담 → 시설규격(Hall A 10,368㎡·520부스 / Hall B 7,290㎡·360부스 / Hall C 10,348㎡ / Hall D 7,000명) → 임대비용 → 임대관련자료(신청서·신고서·도면). 대관 신청→서류→도면→요금 단계별 제공. +- **참가업체**: 각 전시회별 독립 신청 페이지 링크(외부 EMS = cybercoex 연동) + "회사 로그인". 즉 참가업체는 BUSINESS에서 정보만 보고, **신청은 CYBER로 이관**. +- **시공/협력업체**: 전시장·회의실 > **서비스협력업체**(공식 협력사 리스트) + 안전경영 > **온라인작업신고**(현장 작업 신고 = 킨텍스 kxwp에 해당) + 임직원 안전실천강령. → 협력사는 별도 사이트 없이 **BUSINESS 하위 + 안전경영 신고 시스템**에 얹혀 있다. + +### 2-3. 시사점 +코엑스는 **agency(협력사·시공)를 독립 트랙으로 완전 분리하지 않고** BUSINESS 사이트 하위(협력업체 리스트) + 안전경영(작업신고)로 배치했다. 반면 킨텍스는 독립부스 시공에 **등록 장치업체 필수(739개·14분류)**·리깅 구조계산서·규정 반려 리스크가 커서, 킨텍스 도메인에서는 agency를 **독립 트랙**으로 세우는 것이 정당화된다(§4 권고). + +--- + +## 3. CYBER 참가신청 (cybercoex.co.kr / exhibitor.cybercoex.co.kr) — 참가업체 트랜잭션 + +> 직접 크롤 불가(로그인 기반) — WebSearch 결과로 재구성. + +- **위치**: 서울 강남구 영동대로 513(삼성동 COEX). 참가업체 부스+부대시설 온라인 신청/지원 시스템. +- **신청 흐름**(검색 결과 기준): + 1. `cybercoex.co.kr` **로그인** → 참가신청(각 전시회별 `exhibitor.cybercoex.co.kr/exhibition/{host}/{year}/{id}` 딥링크) + 2. **부스비 30%** 청구서 발행일로부터 7일 내 납부 + 3. **부대시설 신청**(전기 등) + 각종 신고서(출입증 등) 제출 + 4. **잔금 70%** + 추가 비용 납부 +- **성격**: 부스와 부대시설(전기·급배수·인터넷 등)을 **온라인으로 신청·결제**하는 트랜잭션 시스템. 킨텍스가 "전시회별 주최자 사무국 시스템(코리아팩 등)으로 파편화"된 것과 달리, 코엑스는 **cybercoex 공통 플랫폼**으로 참가업체 신청을 일원화했다(킨텍스 대비 코엑스의 강점). + +--- + +## 4. 킨텍스(kintex.com) 대비표 + +| 축 | 코엑스(COEX) | 킨텍스(KINTEX) | 시스템 재구성 시사점 | +|---|---|---|---| +| **진입점 분리** | **사이트 3분할**(visitor/business/cyber 도메인) | 단일 사이트(kintex.com), 주최자 랜딩(index_organizer) 정도만 분기 | 킨텍스 시스템은 코엑스식 **트랙 분리**로 IA를 재편(소유자 지시) | +| **관람객(visitor)** | VISITOR 사이트 + 가이드(길찾기·주차·VR·알림) + 맞춤 알림 | 행사일정 검색·교통·주차(iparking) 수준, 관람객 전용 IA 약함 | visitor 트랙에 wayfinding·티켓·배지·맞춤알림 강화(코엑스 차용) | +| **주최자(business)** | BUSINESS 사이트, 임대절차·규격·요금·도면 단계별 | HWP 배정신청서·임대요율표 다운로드 중심 | business 트랙에 M1 자동견적·M2 배치·M6 서류 얹기 | +| **참가업체 신청** | **cybercoex 공통 플랫폼**(부스+부대시설 온라인·결제 일원화) | **전시회별 주최자 사무국 시스템으로 파편화**(공통 플랫폼 부재 = 최대 공백) | business 트랙 참가업체 e-서비스가 킨텍스 최대 차별화 여지 | +| **협력사(agency)** | BUSINESS 하위 협력업체 + 안전경영 온라인작업신고(독립 트랙 아님) | 등록업체 DB(739개·14분류) + kxwp 작업신고. **독립부스 등록업체 시공 필수** | 킨텍스는 agency를 **독립 트랙**으로(등록업체 검증·옥션·시공 — 코엑스보다 강함) | +| **협력사 강제성** | 협력사 리스트 안내 수준 | **미등록 업체 시공 엄금·자체시공 불가** | agency 트랙 = 등록업체 검증 게이트 + M15 옥션의 자연스러운 근거 | +| **온라인 작업신고** | 안전경영 > 온라인작업신고 | kxwp.kintex.com / kxfp.kintex.com | agency 트랙에서 도면제출·규정검증·작업신고 통합 | +| **시설 규격 공개** | Hall A~D ㎡·부스수·수용인원 공개 | 홀1~10 실측(63×171m·5t/㎡·600부스 등) 공개 | 양사 모두 규격 공개 → 자동 배치·견적 가능 | +| **커머스/부대사업** | CoexMall·STORE·F&B·광고·촬영 등 리테일 강함 | 부대시설(뽀로로파크·PBA·연회)·오피스·로케이션·광고 | visitor 트랙 부대서비스 안내로 흡수 가능(P2) | +| **맞춤 알림** | 관심분야 기반 휴대폰 알림 | 없음 | visitor 트랙 리텐션(M10·M12)에 반영 | +| **접근성** | 수어 통역 전면 노출 | 명시 약함 | visitor 트랙 접근성 고지 강화 | + +--- + +## 5. 3-트랙 재구성에 차용할 코엑스 요소 (요약) + +1. **진입점의 물리적 분리** — 랜딩에서 visitor/business/agency로 명확히 갈라 각 서브홈으로 보낸다(코엑스의 3-사이트 = 킨텍스의 3-트랙). +2. **visitor 트랙 = "가이드" 허브** — 오시는 길·주차·실내 길찾기·VR·편의시설·알림마당·문의를 한 곳에(코엑스 가이드 구조). 맞춤 알림·접근성 명시. +3. **business 트랙의 단계별 실무 흐름** — 임대절차→시설규격→요금→서류/도면(코엑스 전시장 메뉴) 위에 킨텍스 M1 자동견적·M2 배치·M6 서류를 얹는다. +4. **참가업체 신청 일원화** — 코엑스 cybercoex처럼 킨텍스의 파편화된 참가업체 신청을 business 트랙 공통 e-서비스로 통합(부스+유틸리티+결제). +5. **agency 트랙 = 협력사 + 작업신고 통합, 단 킨텍스는 독립 트랙으로 승격** — 코엑스는 BUSINESS 하위에 뒀지만, 킨텍스의 등록업체 필수·옥션 도메인은 독립 트랙(등록업체 검증·M15 옥션·시공 대시보드)을 정당화한다. + +--- + +## 6. 분석한 URL 목록 +- 정상 분석: `www.coex.co.kr`(VISITOR 메인), `www.coex.co.kr/guide/`(가이드), `business.coex.co.kr`(BUSINESS 메인) +- 검색 보조: `cybercoex.co.kr` / `exhibitor.cybercoex.co.kr`(참가업체 신청 — 로그인 기반, 직접 크롤 불가), `coexstore.co.kr`·`coexworld.co.kr`(부대/패밀리) +- 접근 불가: cybercoex 로그인 내부, 각 전시회 신청 상세 + +## 출처 +- [코엑스 VISITOR](https://www.coex.co.kr/) +- [코엑스 가이드](https://www.coex.co.kr/guide/) +- [코엑스 BUSINESS](https://business.coex.co.kr/) +- [참가업체 전시부스 온라인신청 (cybercoex)](https://www.cybercoex.co.kr/) +- [exhibitor.cybercoex 참가신청 예시](https://exhibitor.cybercoex.co.kr/exhibition/100/2022/1235) +- [COEX STORE](https://www.coexstore.co.kr/) + + diff --git a/docs/design.md b/docs/design.md index 7c05a3e..a41e791 100644 --- a/docs/design.md +++ b/docs/design.md @@ -1,6 +1,6 @@ # 킨텍스 AI 전시관리 시스템 — UI 디자인 스펙 (design.md) -> 작성: 디자인 에이전트(designer) · 작성일: 2026-07-12 · 버전: **v2.1.2** +> 작성: 디자인 에이전트(designer) · 작성일: 2026-07-12 · 버전: **v2.2** > 근거 문서: `docs/PLANNING.md` **v3.0**(모듈 맵 M1~M18 + §5B 공통/시스템관리 레이어 + §1A 멀티테넌시, 6+2 역할, 나노바나나 표준 샷 세트 S1~S7) · `docs/FEATURE_BACKLOG_100.md`(100대 기능 F001~F100·NFR 4축) · Stitch 산출물 `stitch_kintex_ai_system_architect/`(18화면 + DESIGN.md 3변형) 학습·정합 > **단일 출처(Single Source of Truth)**: 프론트 구현 토큰·컴포넌트 계약은 본 문서가 권위다. Stitch 화면(code.html/screen.png)은 시각 참조로만 사용하며, 상충 시 본 문서를 따른다. > 용도: **각 화면의 "Stitch 프롬프트" 코드블록을 Google Stitch(stitch.withgoogle.com)에 그대로 붙여넣어 화면을 생성**한다. 문서는 한국어, Stitch 프롬프트만 영어. @@ -413,6 +413,15 @@ An enterprise MDI (multiple document interface) application shell for "KINTEX AI | SCR-P7 | 입장권 예매(티켓팅) | M10·M9 | 대 | ✅Stitch | | SCR-P8 | 예매 확인·취소 | M10·M9 | 대 | ✅Stitch | +**웹 — 3-트랙 관문·서브홈 (§3C · SCR-T* · 공개·MDI 비적용·SEO/다국어 · v2.2 신설)** + +| SCR | 화면명 | 모듈 | 역할 | 라우트 | 상태 | +|---|---|---|---|---|---| +| SCR-T0 | 트랙 관문 랜딩(3-트랙 분기) | 공통·M12 | 대 | `/` | 🔲미생성 | +| SCR-T1 | visitor 서브홈(가이드 허브) | M10·M13·M12 | 대 | `/visitor` | 🔲미생성 | +| SCR-T2 | business 서브홈(비즈니스 진입) | M1·M3·M4·M6 | 대 | `/business` | 🔲미생성 | +| SCR-T3 | agency 서브홈(등록업체·옥션) | M15·안전경영 | 협·대 | `/agency` | 🔲미생성 | + **모바일 (§4 · SCR-M*)** | SCR | 화면명 | 모듈 | 역할 | 상태 | @@ -1449,6 +1458,103 @@ A public "check & cancel my ticket booking" page for an exhibition, Korean marke --- +## 3C. 3-트랙 관문·서브홈 (SCR-T*) — 공개 대외 접점 · MDI 비적용 · SEO/다국어 + +> **v2.2 신설.** 코엑스 3-사이트 IA(VISITOR·BUSINESS·CYBER)를 킨텍스 단일 도메인 위에 **visitor / business / agency 3-트랙**으로 정형화한 **얕은 트랙 진입 레이어**다(근거: `docs/PLANNING.md` §2-2 v3.2, `docs/analysis/coex-website.md`, planner 지시서 `_workspace/plan_3track.md`). 신규 화면은 **SCR-T0~T3 4종만**이며 나머지 대외 콘텐츠는 기존 SCR-P*·관람객 앱·업무 딥라우트를 **재사용**한다(회귀 0 목표). +> +> **라우트(얕은 트랙 진입 4개, 신규)**: `/`(SCR-T0 관문)·`/visitor`(SCR-T1)·`/business`(SCR-T2)·`/agency`(SCR-T3). 기존 딥 라우트(`/o/`·`/e/`·`/c/`·`/gallery/`·`/tickets/`)·MDI 셸(§2.7)·티켓 공개 라우트(SCR-P7/P8)·세션키는 **불변**. +> +> **SCR-HOME(인증 홈)과의 관계**: **관문 SCR-T0(`/`)은 미인증 전용 공개 랜딩**이다. 로그인 성공 시 흐름은 기존대로 `/home`(SCR-HOME, AppShell 셸 내부 핀 홈)으로 랜딩한다 — 관문은 SCR-HOME을 대체하지 않으며, 인증 세션이 있는 사용자가 `/`에 도달하면 트랙 셸이 `/home`으로 우선 리다이렉트(딥링크·SEO 크롤러·게스트 티켓 조회는 예외로 공개 유지). 즉 SCR-T0=대외 유입 관문, SCR-HOME=업무 세션 홈으로 역할이 분리된다. +> +> **디자인 토큰**: §1 라이트 테마·`primary-600 #0066B3`·Pretendard·8px 카드·WCAG AA 준수. **신규 토큰 0.** AI 생성 이미지(나노바나나)는 워터마크 "AI 생성 예상 이미지" 상시 노출 규칙 유지. 이모지 금지·선(stroke) SVG 아이콘. + +### 3C-0. 공개 셸(PublicShell) + 3-트랙 스위처 (전 SCR-T*·SCR-P* 공통 크롬) + +- **재사용 전제**: SCR-P*가 쓰는 **PublicShell**(전통 페이지 헤더 GNB·푸터·SSR/CDN·MDI 비적용)을 그대로 재사용하되, **상단에 3-트랙 전환 탭(TrackSwitcher)을 추가**한다. 관문(SCR-T0)은 트랙 미선택 상태, 서브홈(T1~T3)은 해당 트랙 탭 활성. +- **TrackSwitcher 사양**(헤더 최상단 유틸 행 또는 GNB 좌측): 세그먼트 3탭 `관람 · 비즈니스 · 협력사`(라벨=`track.shell.tab.visitor|business|agency`), 각 탭 클릭 시 `/visitor`·`/business`·`/agency` 이동. 좌측에 **KINTEX AI 전시·행사시스템** 워드마크(클릭 시 `/` 관문 복귀). 우측 유틸: 언어 전환(한/영/중/일 `track.shell.lang.*`)·`로그인`(→ SCR-01)·인증 세션 시 `내 홈`(→ `/home`). +- **활성 표시**: 활성 트랙은 `primary-600` 밑줄+굵게, 색 외 `aria-current="page"` 병기(색만으로 전달 금지). 모바일(390px)은 탭을 상단 가로 세그먼트로 유지(스크롤 없이 3탭 균등폭). +- **테넌트 정합(§1A-3)**: 셸은 서브도메인 테넌트 컨텍스트 하에서 해당 테넌트 콘텐츠만 노출(워드마크·브랜딩 분기). 트랙 셸은 `tenant_id` 격리 위에서 동작. +- **접근성**: TrackSwitcher는 `role="tablist"`(수평)·로빙 탭인덱스·포커스 링 `primary-600` 2px. 푸터 `role="contentinfo"`. **i18n 네임스페이스 `track.shell.*`**. + +### SCR-T0 트랙 관문 랜딩 (3-트랙 분기 관문) [공통 · 공개 · 루트 `/`] + +- **대상**: 일반 대중·대외 유입 전원(미인증) · **모듈/P**: 공통 대외 접점(M12 일부 재사용) · P1 · **진입 경로**: 루트 도메인 `/` 직접 진입·검색·광고·QR. 인증 세션 시 `/home` 우선 리다이렉트(위 SCR-HOME 관계 참조) +- **레이아웃**(위→아래, PublicShell·풀블리드 마케팅 밀도): + 1. **PublicShell 헤더 + TrackSwitcher**(관문=트랙 미선택, 워드마크·언어·로그인) + 2. **제품 히어로**: 풀폭 히어로 — 나노바나나 전시 전경 이미지(워터마크 "AI 생성 예상 이미지") 배경 + 대형 헤드라인 "**KINTEX AI 전시·행사시스템**" + 서브카피(전시 기획→시공→관람 전 과정 AI 자동화) + 보조 CTA "관람 사전등록"·"참가 문의". **관람객 시각 1순위**(코엑스 VISITOR 메인 톤) + 3. **3-트랙 대형 분기 카드**(3열 균등, 화면 중앙 히어로 하단 정박): ① `관람객` — "행사 일정·사전등록·오시는 길", CTA "관람 트랙 →"(`/visitor`) ② `주최·참가(비즈니스)` — "대관·자동견적·부스 신청·시공 시안", CTA "비즈니스 트랙 →"(`/business`) ③ `공사·협력사(에이전시)` — "등록업체·공사 옥션·작업신고", CTA "협력사 트랙 →"(`/agency`). 각 카드=아이콘(선 SVG)·대상 라벨·1줄 가치제안·대표 액션. 관람 카드를 시각적으로 약간 크게(1순위) + 4. **행사 하이라이트 레일**(기존 P1 행사 그리드 일부 재사용): 진행 중·예정 행사 가로 스크롤 포스터 카드 6~8장(포스터·행사명·기간·홀·D-day·"사전등록") + 5. **PublicShell 푸터**(회사·교통 GTX-A 킨텍스역·언어·정책) +- **구성요소**: HeroBanner(AI 워터마크)·TrackCard×3·EventRail(포스터 카드)·TrackSwitcher·LanguageSelector·DdayChip·StatusBadge(행사 상태) +- **데이터 원천**: 히어로 배경 = **SCR-01 login-slides 자산/API 재사용**(나노바나나 전경) · 3-트랙 카드 = 정적 구성(트랙 메타) · 행사 하이라이트 = `/api/public/events`(SCR-P1 그리드 자산 재사용, event 테이블 poster_url) → 실 API 재사용, 트랙 카드만 신규 정적 +- **상태**: 로딩(행사 레일 스켈레톤) · 빈(공개 행사 없음 → 히어로+트랙 카드만, 레일 "예정된 전시가 없습니다") · 에러(행사 API 실패 시 트랙 카드는 정상 노출·레일만 재시도) · 인증 세션 감지 시 `/home` 리다이렉트 +- **접근성**: 트랙 카드는 카드 전체 클릭 가능+명시 링크 텍스트, 히어로 배경 이미지 위 헤드라인 대비 확보(오버레이 딤), 색 외 라벨 병기, WCAG AA. **i18n 네임스페이스 `track.gateway.*`**(+ 공유 `track.shell.*`) +- **Stitch 프롬프트**: +``` +A public landing "track gateway" home page for the product "KINTEX AI 전시·행사시스템" (an AI exhibition & event operations platform), Korean, desktop 1440px, light theme, primary blue #0066B3, purple #6D4AFF for AI accents, clean modern marketing design (not an MDI app shell). All UI text in Korean; use line (stroke) SVG icons only, NO emoji. Top: a public header with a "KINTEX AI 전시·행사시스템" wordmark on the left, a 3-tab track switcher "관람 · 비즈니스 · 협력사" (none active on this gateway), and right utilities "언어(한/영/중/일) · 로그인". Full-bleed hero with a photorealistic exhibition-hall render as background (with a faint watermark "AI 생성 예상 이미지" and a dim overlay for text contrast), a large headline "KINTEX AI 전시·행사시스템", a subheading "전시 기획부터 시공·관람까지 전 과정을 AI로 자동화", and two CTAs "관람 사전등록" and "참가 문의". Directly below the hero: three large branching track cards in one row — card 1 "관람객" (slightly larger, primary) with a stroke icon, text "행사 일정 · 사전등록 · 오시는 길" and a button "관람 트랙 →"; card 2 "주최 · 참가 (비즈니스)" with text "대관 · 자동견적 · 부스 신청 · 시공 시안" and a button "비즈니스 트랙 →"; card 3 "공사 · 협력사 (에이전시)" with text "등록업체 · 공사 옥션 · 작업신고" and a button "협력사 트랙 →". Below: a horizontal scrolling rail of event poster cards (poster, title, dates, hall, a "D-25" day chip, "사전등록" button) titled "진행 중 · 예정 전시". Footer with company info and "오시는 길 · GTX-A 킨텍스역". Spacious, multilingual, conversion-oriented gateway aesthetic; rounded 8px cards, WCAG AA contrast. +``` + +### SCR-T1 visitor 서브홈 (관람객 공개 홈 · 가이드 허브) [visitor · 공개 · `/visitor`] + +- **대상**: 일반 대중·관람객(게스트+회원) · **모듈/P**: M10(사전등록·티켓)·M13(실내 길찾기)·M12(공지) · P1 · **진입 경로**: 관문 SCR-T0 "관람 트랙" · TrackSwitcher "관람" · 직접 `/visitor` +- **레이아웃**(위→아래, PublicShell·SCR-P1 확장): + 1. **PublicShell 헤더 + TrackSwitcher**("관람" 활성) + 2. **관람 히어로 + 주 CTA**: 관람객 톤 히어로 + "사전등록"·"입장권 예매"(→ SCR-P4·P7) 이중 CTA + 맞춤 알림 유도("관심 분야 알림 받기") + 3. **행사 일정 그리드**(SCR-P1 행사 카드 재사용): 진행 중·예정 행사 카드 그리드(포스터·행사명·기간·홀·상태 배지·"사전등록")+전시장 세그먼트 필터(전체/홀, 동적 옵션) + 4. **방문 가이드 허브**(코엑스 가이드 차용 — 2×3 카드): ① 교통(GTX-A 킨텍스역 도보 3분·광역버스) ② 주차(iparking 실시간·요금·게이트) ③ **실내 길찾기**(M13 wayfinding 딥링크) ④ 편의시설(식음·수유실·물품보관·ATM) ⑤ 접근성·편의(휠체어·수어통역 고지) ⑥ 고객문의(FAQ·연락처). 각 카드 선 SVG 아이콘+1줄 설명+링크 + 5. **공지·알림마당**: 최근 공지 5건 리스트(§5B notice 재사용)+더보기 + 6. **PublicShell 푸터** +- **구성요소**: HeroBanner·EventGrid(P1 카드)·GuideHubCard×6·NoticeList·LanguageSelector·CTA(사전등록·티켓·알림) +- **데이터 원천**: 행사 그리드 = `/api/public/events`(SCR-P1 자산 재사용) · 사전등록/티켓 CTA = SCR-P4/P7 딥링크 · 실내 길찾기 = M13 wayfinding(SCR-M9 계열) 딥링크 · 공지 = §5B notice `/work/notice` 공개 서브셋 → 실 API 재사용, 가이드 정적 콘텐츠(교통·주차·편의 안내)는 CMS/정적. **SEO·다국어 적용, MDI 비적용** +- **상태**: 로딩(행사·공지 스켈레톤) · 빈(행사 없음 "예정된 전시가 없습니다"·공지 없음) · 에러(영역별 재시도, 가이드 허브는 정적이라 상시 노출) +- **접근성**: 가이드 카드 링크 텍스트 명시, 접근성 안내 카드 자체가 WCAG AA·수어/휠체어 정보 제공, 색 외 라벨 병기. **i18n 네임스페이스 `track.visitor.*`**(+ 공유 `track.shell.*`) +- **Stitch 프롬프트**: +``` +A public visitor sub-home / visit-guide hub page for the product "KINTEX AI 전시·행사시스템", visitor track, Korean, desktop 1440px, light theme, primary blue #0066B3, clean marketing design (not MDI). All UI text in Korean; line (stroke) SVG icons only, NO emoji. Top: public header with "KINTEX AI 전시·행사시스템" wordmark, a 3-tab track switcher "관람 · 비즈니스 · 협력사" with "관람" active (underlined, aria-current), and right utilities "언어 · 로그인". A visitor-toned hero with headline "전시 관람, 여기서 시작하세요", dual CTAs "사전등록" and "입장권 예매", and a subtle "관심 분야 알림 받기" prompt. Below: an event schedule grid of cards (poster, title, dates "2026.09.05–09.08", hall, a status badge, "사전등록" button) with a venue segment filter "전체 · 제1전시장 · 제2전시장". Then a "방문 가이드" hub section as a 2×3 grid of cards, each with a stroke icon, title and one-line text and a link: "교통 · GTX-A 킨텍스역 도보 3분", "주차 · 실시간 주차 안내", "실내 길찾기", "편의시설 · 식음·수유실·물품보관", "접근성 · 휠체어·수어통역 안내", "고객문의 · FAQ·연락처". Then a "공지사항" list of 5 recent notices with a "더보기" link. Footer. Helpful, welcoming, accessible public visitor-guide aesthetic; rounded 8px cards, WCAG AA contrast. +``` + +### SCR-T2 business 서브홈 (비즈니스 안내·진입 홈) [business · 공개 · `/business`] + +- **대상**: 전시주최자·참가업체(미인증 대외) · **모듈/P**: M1(대관·자동견적)·M3/M4(부스 신청·유틸리티)·M6(서류) 안내 · P1 · **진입 경로**: 관문 SCR-T0 "비즈니스 트랙" · TrackSwitcher "비즈니스" · 직접 `/business` +- **레이아웃**(위→아래, PublicShell·SCR-P6 확장·코엑스 BUSINESS+CYBER 차용): + 1. **PublicShell 헤더 + TrackSwitcher**("비즈니스" 활성) + 2. **비즈니스 히어로**: B2B 실무 톤 헤드라인 "전시 개최·참가, 온라인 신청 일원화" + "로그인"·"신청/문의" CTA + 3. **2-분기 가치 제안 카드**(2열 대형): ① **주최자** — 홀 임대 절차(문의→가견적→계약→배정) + "자동견적(M1)"·"홀 배정·플로어플랜(M2)" 안내 + 요금/시설 규격 개요 + CTA "대관 문의·로그인" ② **참가업체** — 부스 신청·서류·시공 시안(부스 유형·유틸리티 신청 M4·규정 사전검증·나노바나나 시공 시안 M5) + CTA "참가 신청·로그인". **온라인 신청 일원화 강조**(코엑스 CYBER 차용 — "모든 신청·결제를 온라인에서") + 4. **임대 절차 흐름 스텝**(코엑스 BUSINESS 임대절차): 가로 스텝 인디케이터 "문의 → 가견적 → 계약 → 홀 배정 → 부스 신청 → 시공·검수"(각 스텝 1줄 설명, 해당 모듈 배지) + 5. **요금·서류 안내**: 부스 유형·요율 개요(SCR-P6 재사용) + 주요 서류(배정신청서·방염·구조계산서) 다운로드/안내 + 6. **로그인/문의 CTA 밴드**: "이미 계정이 있으신가요? 로그인"(→ SCR-01 → 역할 판정 → 주최자 SCR-02 / 참가 SCR-05) + 문의 폼(SCR-P6 재사용) + 7. **PublicShell 푸터** +- **구성요소**: HeroBanner·ValuePropCard×2(주최자·참가)·ProcessStepper·RateOverview·DocList·InquiryForm(P6)·LoginCTA·TrackSwitcher +- **데이터 원천**: 가치 제안·절차·요금 = 정적/CMS 안내(M1·M2·M4·M5·M6 소개) · 부스 유형·요율 = SCR-P6 자산 재사용 · 문의 폼 = SCR-P6 재사용 · 로그인 CTA = SCR-01 딥링크(성공 시 역할 홈 SCR-02/05) → 신규 트랜잭션 없음(안내+진입). **SEO·다국어, MDI 비적용** +- **상태**: 로딩(요금·안내 스켈레톤) · 빈(공지성 콘텐츠 없음 시 기본 안내 유지) · 에러(문의 전송 실패 인라인 재시도) · 문의 전송 완료 토스트 +- **접근성**: 2-분기 카드 각 CTA 명시 링크, 절차 스텝 `ol`+스크린리더 순서, 색 외 배지 텍스트, WCAG AA. **i18n 네임스페이스 `track.business.*`**(+ 공유 `track.shell.*`) +- **Stitch 프롬프트**: +``` +A public business sub-home / entry page for the product "KINTEX AI 전시·행사시스템", business track (for exhibition organizers and exhibitors), Korean, desktop 1440px, light theme, primary blue #0066B3, purple #6D4AFF for AI, B2B professional tone (not MDI). All UI text in Korean; line (stroke) SVG icons only, NO emoji. Top: public header with "KINTEX AI 전시·행사시스템" wordmark, a 3-tab track switcher "관람 · 비즈니스 · 협력사" with "비즈니스" active, right utilities "언어 · 로그인". Hero headline "전시 개최·참가, 온라인 신청 일원화" with CTAs "신청·문의" and "로그인". Below, two large value-proposition cards side by side: left "주최자 · 홀 임대" listing "대관 절차 · 자동견적(AI) · 홀 배정·플로어플랜 · 요금/시설 규격" with a button "대관 문의·로그인"; right "참가업체 · 부스 신청" listing "부스 신청 · 유틸리티 신청 · 규정 사전검증 · AI 시공 시안" with a button "참가 신청·로그인" (AI items marked with a small purple "AI" chip). Then a horizontal process stepper "문의 → 가견적 → 계약 → 홀 배정 → 부스 신청 → 시공·검수" with a one-line caption per step. Then a "요금·서류 안내" section with booth-type rate cards (조립부스 / 독립부스 / 프리미엄) and a document list (배정신청서 · 방염 확인서 · 구조계산서). A login/inquiry CTA band "이미 계정이 있으신가요? 로그인" plus a compact inquiry form (회사명, 담당자, 연락처, 희망 홀, 문의 내용, "문의 보내기"). Footer. Trustworthy B2B lead-generation and online-application aesthetic; rounded 8px cards, tabular numerals for rates, WCAG AA. +``` + +### SCR-T3 agency 서브홈 (에이전시 안내·등록업체 진입 홈) [agency · 공개 · `/agency`] + +- **대상**: 공사·장치·협력업체(미인증 대외)·등록업체 · **모듈/P**: M15(공사 옥션·역경매)·안전경영(작업신고)·등록업체 검증 · P1 · **진입 경로**: 관문 SCR-T0 "협력사 트랙" · TrackSwitcher "협력사" · 직접 `/agency` +- **레이아웃**(위→아래, PublicShell·코엑스 서비스협력업체+안전경영 차용·킨텍스 옥션 차별점 강조): + 1. **PublicShell 헤더 + TrackSwitcher**("협력사" 활성) + 2. **에이전시 히어로**: "킨텍스 공식 등록업체로 전시 시공에 참여하세요" + "등록 안내"·"등록업체 로그인" CTA. **킨텍스 차별점(옥션) 강조** 서브카피 + 3. **등록업체 안내 카드**: 등록업체 현황(739개사·14개 분류) + **미등록 업체 시공 엄금·자체시공 불가 필수 고지**(warning 톤 안내) + 등록 절차(신청→자격심사→등록→수주 자격) + CTA "등록 신청" + 4. **진행 중 공사 옥션 공고 리스트(M15 · 역경매)**: 카드/행 리스트 — 옥션명·대상 부스/행사·예산 범위·마감 D-day(DdayChip)·응찰 현황(참여 업체 수)·상태 배지. 각 행 "상세·응찰"(로그인 유도). **킨텍스 차별점(역경매 옥션) 히어로 다음으로 크게** 배치 + 5. **작업신고·규정 안내**(코엑스 안전경영 온라인작업신고): 현장 작업신고 절차·안전 규정(금지작업·소음·리깅 구조계산서)·필수 서류(방염·보험) 안내 카드 + "작업신고 하기"(로그인) + 6. **등록업체 로그인 CTA 밴드**: "등록업체 로그인"(→ SCR-01 → 장치업체 판정 → 수주/응찰 대시보드 SCR-27/28) + 7. **PublicShell 푸터** +- **구성요소**: HeroBanner·RegistryInfoCard(고지)·AuctionList(M15 공고 카드·DdayChip·StatusBadge)·SafetyGuideCard·LoginCTA·TrackSwitcher +- **데이터 원천**: 등록업체 현황·절차 = 정적/CMS 안내(739·14분류·등록 게이트) · **진행 중 옥션 = M15 공개 서브셋**(`/api/public/auctions` 또는 옥션 목록 SCR-24 공개 읽기 서브셋 — 응찰은 로그인 후 SCR-27/28) · 작업신고·규정 = 정적 안내 · 로그인 CTA = SCR-01 딥링크(성공 시 SCR-27/28) → 옥션 리스트만 실 API(공개 읽기), 나머지 안내 정적. **SEO·다국어, MDI 비적용** +- **상태**: 로딩(옥션 리스트 스켈레톤) · 빈(진행 중 옥션 없음 "현재 진행 중인 공사 옥션이 없습니다") · 에러(옥션 API 실패 재시도, 등록·규정 안내는 정적 상시 노출) · 마감 임박 옥션 `warning` D-day 강조 +- **접근성**: 필수 등록 고지는 색 외 텍스트로 명확히("미등록 업체는 시공에 참여할 수 없습니다"), 옥션 D-day 색+텍스트 병기, 로그인 CTA 명시, WCAG AA. **i18n 네임스페이스 `track.agency.*`**(+ 공유 `track.shell.*`) +- **Stitch 프롬프트**: +``` +A public agency (contractor / booth-construction partner) sub-home page for the product "KINTEX AI 전시·행사시스템", agency track, Korean, desktop 1440px, light theme, primary blue #0066B3, warning orange #B45309, clean B2B tone (not MDI). All UI text in Korean; line (stroke) SVG icons only, NO emoji. Top: public header with "KINTEX AI 전시·행사시스템" wordmark, a 3-tab track switcher "관람 · 비즈니스 · 협력사" with "협력사" active, right utilities "언어 · 등록업체 로그인". Hero headline "킨텍스 공식 등록업체로 전시 시공에 참여하세요" with a subheading emphasizing the differentiator "공사 옥션(역경매)로 투명하게 수주", and CTAs "등록 안내" and "등록업체 로그인". Below: a "등록업체 안내" card showing "등록업체 739개사 · 14개 분류" with a prominent warning-toned notice "미등록 업체는 전시 시공에 참여할 수 없습니다 (자체시공 불가)" and a registration process "신청 → 자격심사 → 등록 → 수주 자격", button "등록 신청". Then, prominently, a "진행 중 공사 옥션 (역경매)" list of auction announcement rows/cards — each with auction name, target booth/event, budget range, a red/orange "D-3" day chip, bidder count "응찰 4개사", a status badge, and a "상세·응찰" link (login-gated). Then a "작업신고 · 안전 규정" section with cards for on-site work report procedure, prohibited works / noise limit / rigging structural calc, and required documents (방염·보험), with a button "작업신고 하기". A bottom login CTA band "등록업체 로그인". Footer. Professional partner-portal aesthetic highlighting the reverse-auction differentiator; rounded 8px cards, tabular numerals, WCAG AA contrast. +``` + +--- + ## 4. 모바일 대응 (390px) 모바일은 **조회·승인·현장** 시나리오 전용(PLANNING.md §8). 캔버스 편집(SCR-03, 07)과 스펙 편집(SCR-06 좌패널)은 모바일 미제공 — 뷰어+승인 액션만. 아래 두 화면은 **모바일 전용 신규 화면**, 나머지는 반응형 축소. @@ -1666,6 +1772,7 @@ A mobile "my ticket wallet" screen for an exhibition visitor, 390px width, light | 버전 | 일자 | 작성자 | 내용 | |---|---|---|---| +| **v2.2** | 2026-07-12 | designer | **3-트랙(visitor/business/agency) 대외 접점 재편 — 신규 4화면 SCR-T0~T3 순증(planner 지시서 `_workspace/plan_3track.md`·PLANNING v3.2 §2-2·`docs/analysis/coex-website.md` 근거).** 코엑스 3-사이트 IA(VISITOR·BUSINESS·CYBER)를 킨텍스 단일 도메인 위 3-트랙 얕은 진입 레이어로 정형화. ①**§3C 신설** — 3C-0 공개 셸(PublicShell) 재사용+상단 3-트랙 스위처(TrackSwitcher, `role=tablist`·`관람/비즈니스/협력사`·워드마크 `/` 복귀·언어·로그인·`내 홈`) 사양, SCR-T0 관문 랜딩(루트 `/`·제품 히어로 "KINTEX AI 전시·행사시스템"+3-트랙 대형 분기 카드+행사 하이라이트 레일, 관람 1순위), SCR-T1 visitor 서브홈(`/visitor`·행사 그리드+사전등록/티켓 CTA+2×3 방문 가이드 허브(교통 GTX-A·주차·M13 실내 길찾기·편의·접근성·문의)+공지), SCR-T2 business 서브홈(`/business`·주최자/참가 2-분기 가치제안+임대 절차 스텝+요금·서류+로그인/문의 CTA→SCR-01→SCR-02/05, 온라인 신청 일원화 강조), SCR-T3 agency 서브홈(`/agency`·등록업체 안내 739·14분류·미등록 시공 엄금 고지+진행 중 M15 공사 옥션 역경매 리스트+작업신고·규정+등록업체 로그인→SCR-27/28, 옥션 차별점 강조) — 각 화면 레이아웃·구성요소·데이터 원천(기존 API 재사용 매핑: login-slides·`/api/public/events`·notice·SCR-P6·M15 공개 서브셋)·상태(로딩/빈/에러/degraded)·접근성·i18n 네임스페이스(`track.gateway/visitor/business/agency/shell.*`)+영어 Stitch 프롬프트(Precision Enterprise AI·1440·NO emoji·선 SVG·WCAG AA). ②**SCR-HOME 관계 명시**: 관문 SCR-T0(`/`)=미인증 전용 공개 랜딩, 인증 세션 시 `/home`(SCR-HOME) 우선 리다이렉트(딥링크·SEO·게스트 티켓 조회 예외). ③**§2.8-2 인벤토리**에 SCR-T* 표 추가(집계 85→**89화면**, 미생성 2→6: SCR-HOME·M3+T0~T3). **경계 준수**: 기존 SCR·라우트·MDI 셸(§2.7)·티켓 공개 라우트(SCR-P7/P8)·세션키 불변, 신규 라우트는 얕은 트랙 진입 4개만, ops/admin 트랙 외부 유지, §1A 멀티테넌시 정합. §1 토큰 권위·**신규 토큰 0**, 기존 화면 스펙·PLANNING.md·src 무수정 | | **v2.1.2** | 2026-07-12 | designer | **로그인 후 메인 홈(SCR-HOME) 신설 + 로그인 랜딩 흐름 변경 + 셸 하단 상태바(ShellFooter) 신설(소유자 지시 2026-07-12).** ①**§3 SCR-HOME 신설**(라우트 `/home`, AppShell 셸 내부 핀 홈 탭) — 인사·요약 KPI 스트립 4타일(진행 전시·오늘 체크인·D-임박·미결 결재, 기존 실 API 재사용), 행사소개 배너 캐러셀(**SCR-01 login-slides 자산/API 재사용**·자동슬라이드·좌우 내비), 현재·예정 전시 일정 캘린더(**WISE `CalendarView` 패턴 참조** — 월 그리드 6주×7열·요일 헤더·오늘 강조·단일일 색점칩/기간 spanning bar·"+N" 팝업 + **전시장 세그먼트 필터(동적 옵션·하드코딩 금지 — `전체`+홀 마스터 센터 구분 distinct, 3관·4관 확장 대비)** 기본값 전체, `/api/events/calendar`+`/api/public/events`+홀 마스터 옵션 API 재사용), **"진행 중·다가오는 전시" 쇼케이스(확정판 — 배너 아래 가로 스크롤 포스터 카드 레일 8~12장·세로 2:3 포스터+행사명/기간/hall_label/상태배지/D-day·좌우 화살표·탭 `진행 중|이번 달|다음 달`·poster_url 부재 시 그라디언트+행사명 폴백, 데이터=event 테이블 poster_url V32 크롤 34건)**, 우측 컬럼 4위젯 스택(**내 할 일(역할 기반, 최상단) — 주최자=미결 결재/서류 마감 D-n/홀 배정 대기/옥션 낙찰 대기·참가업체=신고서류/설계 확정/견적·청구·공사업체=응찰 마감/시공 일정·관리자=승인 대기/점검, 행=상태점+작업명+대상+D-day 클릭 이동·건수 배지·0건 "모두 완료"+CTA, 데이터=§5B approval·M6·M15·M9 집계 조합 — 신규 통합 API `GET /api/home/todos` 계약 제안 명시**·공지 최근 5건+더보기(§5B notice `/work/notice`)·**빠른 작업 2×3 바로가기 그리드(역할별)**·**최근 활동 타임라인 5건(알림 피드 재사용)**), 내 행사 워크스페이스 카드 그리드(참여 행사·카드 클릭→역할별 대시보드·빈 상태 초대코드 안내) + **KPI 4타일 역할별 구성 명시(주최자/참가업체/공사업체/관리자 예시 세트)** + **밀도 원칙 4항(소유자 추가 지시)**: 대형 공백 금지·12컬럼 컴팩트(섹션 간 24px 표준/32px 상한)·배너 높이 220~260px 제한·좌우 컬럼 세로 균형·전 빈 상태 안내+행동 버튼(CTA) 조합. **본 판이 SCR-HOME 스펙 확정판** — 레이아웃·상태(영역별 로딩/빈/에러)·데이터 원천 매핑·접근성(WCAG AA·i18n `home.`·이모지 금지 선SVG·`prefers-reduced-motion`)+영어 Stitch 프롬프트(Precision Enterprise AI·1440·footer 포함). ②**SCR-01 흐름 수정**: 로그인 성공→`/home` 랜딩, "행사 워크스페이스 선택" phase 제거(SCR-HOME 섹션으로 흡수), SCR-01은 순수 로그인 화면으로 축소. ③**§2-2 ShellFooter 신설**(약 36px, 전 셸 화면 공통): 좌측 저작권 "© 2026 KINTEX. All rights reserved.", 우측 시스템 상태 점(정상/점검·색외 텍스트 병기)·앱 버전·고객지원 링크, `role="contentinfo"`·라이트/다크 토큰·WCAG AA·i18n `shell.footer.*`, 모바일 미적용(더보기 이관). §2.7-1 셸 레이아웃 다이어그램에 하단 36px 행 추가. ④**§2-1 사이트맵·§2.8-2 인벤토리**에 SCR-HOME 반영(집계 84→**85화면**, 미생성 0→2: SCR-HOME+SCR-M3). §1 토큰 권위 유지·**신규 토큰 0**, 기존 화면 스펙·PLANNING.md·src 무수정 | | **v2.1.1** | 2026-07-12 | designer | **Stitch 잔여 39화면 전량 확보(64/64) 상태 반영 + 이전 확보 25화면 상태 정합 + 집계 갱신.** 2026-07-12 Stitch 수확 재실행으로 미확보 39화면이 전량 확보됨 — §2.8-2 인덱스 상태 컬럼만 `🔲미생성`→`✅Stitch` 교체(웹코어 SCR-22·23·25·26·27·29·30·32~51, 관리자 SCR-A5·A6·A8·A9, 공개 SCR-P1~P7, 모바일 SCR-M15). 추가로 이전 세션 확보분 25화면(디스크 code.html 존재 검증: 웹코어 SCR-18·19·20·21·24·28·31, 관리자 SCR-A1~A4·A7·A10, 공개 SCR-P8, 모바일 SCR-M4~M14)도 동일 규칙으로 정합화 — 총 64화면 상태 교체. §2.8-2 집계 문장 갱신: ✅Stitch 18→**83** · 🔲미생성 64→**0**(Stitch 미확보는 SCR-M3 1건뿐). 화면 스펙·프롬프트·구조 무수정. 수확 상세 `_workspace/stitch_gen/harvest_report.md` | | **v2.1** | 2026-07-11 | designer | **입장권 예매 4화면 추가(M10 티켓 기획 대비 화면 갭 해소).** PLANNING v3.0 M10이 티켓을 기획 범위에 포함하나 design.md v2.0 인벤토리엔 예매 흐름 화면이 없던 갭을 메움 — 기존 번호 체계 이어서 순증(재번호화·기존 스펙 수정 없음). ①**§2.8-1 매트릭스**: M10 행에 SCR-P7·P8/M14·M15, M9 행에 SCR-P7(티켓결제 연계) 반영. ②**§2.8-2 인덱스**: 공개사이트에 SCR-P7(입장권 예매)·SCR-P8(예매 확인·취소), 모바일에 SCR-M14(모바일 티켓 예매)·SCR-M15(내 티켓 지갑) 추가, 집계 80→**84화면**(공개 6→8·모바일 13→15, 미생성 60→64). ③**§3B**: SCR-P7(행사·권종→예매자→결제→완료 다단계, 게스트+회원, 결제 PG 어댑터 위임·카드번호 입력 UI 없음)·SCR-P8(예매번호+이메일 조회·QR 티켓 상세·환불정책·취소) 상세+영어 Stitch 프롬프트. ④**§4**: SCR-M14(SCR-P7 모바일 최적화 390px·48px 터치)·SCR-M15(보유 티켓·QR 풀스크린 밝기부스트·오프라인 표시·취소 진입, 티켓→체크인→배지(SCR-M5) 전환 명시) 상세+프롬프트. §5 가이드 모바일 범위 M1~M13→M1~M15. **보안·불변 준수**: 결제 화면 카드번호 저장 UI 금지(PG 위임 명시)·PII 마스킹·WCAG AA·i18n·라이트/다크. §1 토큰 권위 유지, 신규 토큰 0. PLANNING.md·기존 화면 스펙·src 무수정 | diff --git a/mobile/app.json b/mobile/app.json index 8590e05..a871cd3 100644 --- a/mobile/app.json +++ b/mobile/app.json @@ -2,39 +2,53 @@ "expo": { "name": "KINTEX AI 전시관리", "slug": "kintex", + "owner": "zioinfo", "scheme": "kintex", "version": "0.1.0", "orientation": "portrait", "userInterfaceStyle": "light", - "newArchEnabled": false, + "icon": "./assets/icon.png", "splash": { + "image": "./assets/splash.png", "resizeMode": "contain", "backgroundColor": "#004C86" }, - "assetBundlePatterns": ["**/*"], + "assetBundlePatterns": [ + "**/*" + ], "ios": { "supportsTablet": true, "bundleIdentifier": "kr.co.zioinfo.kintex" }, "android": { "package": "kr.co.zioinfo.kintex", + "versionCode": 1, "adaptiveIcon": { + "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#0066B3" } }, "web": { "bundler": "metro", - "output": "single" + "output": "single", + "favicon": "./assets/favicon.png" }, "plugins": [ "expo-router", - "expo-secure-store" + "expo-secure-store", + "expo-font" ], "experiments": { "typedRoutes": false }, "extra": { - "apiBase": "https://kintex.zioinfo.co.kr" + "apiBase": "https://kintex.zioinfo.co.kr", + "router": { + "origin": false + }, + "eas": { + "projectId": "80b0a6ae-a2f6-4a25-8a9e-daa666543647" + } } } } diff --git a/mobile/eas.json b/mobile/eas.json new file mode 100644 index 0000000..1c6418e --- /dev/null +++ b/mobile/eas.json @@ -0,0 +1,27 @@ +{ + "cli": { + "version": ">= 10.0.0", + "appVersionSource": "local" + }, + "build": { + "development": { + "developmentClient": true, + "distribution": "internal", + "android": { "buildType": "apk" } + }, + "preview": { + "distribution": "internal", + "android": { + "buildType": "apk" + } + }, + "production": { + "android": { + "buildType": "app-bundle" + } + } + }, + "submit": { + "production": {} + } +} diff --git a/mobile/package-lock.json b/mobile/package-lock.json new file mode 100644 index 0000000..13e9dbf --- /dev/null +++ b/mobile/package-lock.json @@ -0,0 +1,15339 @@ +{ + "name": "kintex-mobile", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "kintex-mobile", + "version": "0.1.0", + "dependencies": { + "@expo/vector-icons": "^14.0.3", + "@react-native-async-storage/async-storage": "1.23.1", + "expo": "^51.0.39", + "expo-constants": "~16.0.2", + "expo-font": "~12.0.10", + "expo-image-picker": "~15.1.0", + "expo-linking": "~6.3.1", + "expo-router": "~3.5.23", + "expo-secure-store": "~13.0.2", + "expo-splash-screen": "~0.27.7", + "expo-status-bar": "~1.12.1", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-native": "0.74.5", + "react-native-gesture-handler": "~2.16.1", + "react-native-safe-area-context": "4.10.5", + "react-native-screens": "3.31.1", + "react-native-svg": "15.2.0", + "react-native-web": "~0.19.10" + }, + "devDependencies": { + "@babel/core": "^7.20.0", + "@types/react": "~18.2.45", + "typescript": "~5.3.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.11" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", + "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.7.tgz", + "integrity": "sha512-EtU0Hi3GvrTqD56xKmZvV/uCXK2ZbwVNPNLAquVItcAZpUhkXwWlo3Fmj0c2LxgSf2I8IDULeAepwNP1OefLXg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-decorators": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.29.7.tgz", + "integrity": "sha512-p+G5BNXDcy3bOXplhY4HybQ1GxH3i2Tppmdm/3epyRu2VgJJZuUlZ61MqRTg582Q7ZLBdP7fePYvsumSEkMxcQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", + "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-logical-assignment-operators instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.29.7.tgz", + "integrity": "sha512-9MTTLbF39X6sqM92JPEsoI7++26hjZvzkxKZy64aMhWLH2mPkJ/Q3AV4QLmls3R14FpSpkOwQQfUh962JGQxxg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.29.7.tgz", + "integrity": "sha512-foag0BB37ROhdeIX9O8G0jX7hw0UekJc04cHMrYLOnrErsnBKqJGHJ8eDRpoCFZBvEPPygmmtw4qyU97qa4oOw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.29.7.tgz", + "integrity": "sha512-ajMX6QPcyomotqwpzhkYGxcK2i/us0rs1Qo9QvUpa+Fca0FTmqrzKrctoIYLMxcOhGZldGT/BAVkRGTWBiR8gQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz", + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.29.7.tgz", + "integrity": "sha512-wRHeUjUjCZnMHmiO5bRgjFLcoEh7JyTdByOW11ahhwNa4V0bmeGEaIvt51yq0zQp2yWIpqfxXXPyUP6GFJZHOQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-flow": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", + "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz", + "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz", + "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz", + "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.7.tgz", + "integrity": "sha512-xmAscdE/AsqRW7vutbPNoUmu/nF5SrLKPs7aoJgEjo35lLKA/Bc0i2rMv/hr1+Y0o1bQCiVtith3u2vdgRL39Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz", + "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz", + "integrity": "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-syntax-typescript": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-flow": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.29.7.tgz", + "integrity": "sha512-KYIRV0BuaN68CDdsqFkAD7MU7yipUqQNuNElwATdxaIdpTjhvtY82QvkBJs7zV3Evxj2jFAAZ1iO8nyy0nhjqA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-transform-flow-strip-types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz", + "integrity": "sha512-C+PV1TFUPTmBQGoPBL8j2QmLpZ117YTCwxIZeJOM96GbYMFSc7/pOXU5lVykwnZxyTqQxRsvoRk6f2FktZgGHA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-transform-react-display-name": "^7.29.7", + "@babel/plugin-transform-react-jsx": "^7.29.7", + "@babel/plugin-transform-react-jsx-development": "^7.29.7", + "@babel/plugin-transform-react-pure-annotations": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.29.7.tgz", + "integrity": "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-typescript": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.29.7.tgz", + "integrity": "sha512-AMGJoWuES861riy6pcB0fphE1YXybtQnBYQMuIyPv6mKLiosfa79BKTnAOyx215c/3RJPJpdQwoHZ3earVH7AA==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "license": "MIT", + "dependencies": { + "@types/hammerjs": "^2.0.36" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@expo/bunyan": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@expo/bunyan/-/bunyan-4.0.1.tgz", + "integrity": "sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==", + "license": "MIT", + "dependencies": { + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@expo/cli": { + "version": "0.18.31", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.18.31.tgz", + "integrity": "sha512-v9llw9fT3Uv+TCM6Xllo54t672CuYtinEQZ2LPJ2EJsCwuTc4Cd2gXQaouuIVD21VoeGQnr5JtJuWbF97sBKzQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "@expo/code-signing-certificates": "0.0.5", + "@expo/config": "~9.0.0-beta.0", + "@expo/config-plugins": "~8.0.8", + "@expo/devcert": "^1.0.0", + "@expo/env": "~0.3.0", + "@expo/image-utils": "^0.5.0", + "@expo/json-file": "^8.3.0", + "@expo/metro-config": "0.18.11", + "@expo/osascript": "^2.0.31", + "@expo/package-manager": "^1.5.0", + "@expo/plist": "^0.1.0", + "@expo/prebuild-config": "7.0.9", + "@expo/rudder-sdk-node": "1.1.1", + "@expo/spawn-async": "^1.7.2", + "@expo/xcpretty": "^4.3.0", + "@react-native/dev-middleware": "0.74.85", + "@urql/core": "2.3.6", + "@urql/exchange-retry": "0.3.0", + "accepts": "^1.3.8", + "arg": "5.0.2", + "better-opn": "~3.0.2", + "bplist-creator": "0.0.7", + "bplist-parser": "^0.3.1", + "cacache": "^18.0.2", + "chalk": "^4.0.0", + "ci-info": "^3.3.0", + "connect": "^3.7.0", + "debug": "^4.3.4", + "env-editor": "^0.4.1", + "fast-glob": "^3.3.2", + "find-yarn-workspace-root": "~2.0.0", + "form-data": "^3.0.1", + "freeport-async": "2.0.0", + "fs-extra": "~8.1.0", + "getenv": "^1.0.0", + "glob": "^7.1.7", + "graphql": "15.8.0", + "graphql-tag": "^2.10.1", + "https-proxy-agent": "^5.0.1", + "internal-ip": "4.3.0", + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1", + "js-yaml": "^3.13.1", + "json-schema-deref-sync": "^0.13.0", + "lodash.debounce": "^4.0.8", + "md5hex": "^1.0.0", + "minimatch": "^3.0.4", + "node-fetch": "^2.6.7", + "node-forge": "^1.3.1", + "npm-package-arg": "^7.0.0", + "open": "^8.3.0", + "ora": "3.4.0", + "picomatch": "^3.0.1", + "pretty-bytes": "5.6.0", + "progress": "2.0.3", + "prompts": "^2.3.2", + "qrcode-terminal": "0.11.0", + "require-from-string": "^2.0.2", + "requireg": "^0.2.2", + "resolve": "^1.22.2", + "resolve-from": "^5.0.0", + "resolve.exports": "^2.0.2", + "semver": "^7.6.0", + "send": "^0.18.0", + "slugify": "^1.3.4", + "source-map-support": "~0.5.21", + "stacktrace-parser": "^0.1.10", + "structured-headers": "^0.4.1", + "tar": "^6.0.5", + "temp-dir": "^2.0.0", + "tempy": "^0.7.1", + "terminal-link": "^2.1.1", + "text-table": "^0.2.0", + "url-join": "4.0.0", + "wrap-ansi": "^7.0.0", + "ws": "^8.12.1" + }, + "bin": { + "expo-internal": "build/bin/cli" + } + }, + "node_modules/@expo/cli/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/code-signing-certificates": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@expo/code-signing-certificates/-/code-signing-certificates-0.0.5.tgz", + "integrity": "sha512-BNhXkY1bblxKZpltzAx98G2Egj9g1Q+JRcvR7E99DOj862FTCX+ZPsAUtPTr7aHxwtrL7+fL3r0JSmM9kBm+Bw==", + "license": "MIT", + "dependencies": { + "node-forge": "^1.2.1", + "nullthrows": "^1.1.1" + } + }, + "node_modules/@expo/config": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-9.0.4.tgz", + "integrity": "sha512-g5ns5u1JSKudHYhjo1zaSfkJ/iZIcWmUmIQptMJZ6ag1C0ShL2sj8qdfU8MmAMuKLOgcIfSaiWlQnm4X3VJVkg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "~7.10.4", + "@expo/config-plugins": "~8.0.8", + "@expo/config-types": "^51.0.3", + "@expo/json-file": "^8.3.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0", + "semver": "^7.6.0", + "slugify": "^1.3.4", + "sucrase": "3.34.0" + } + }, + "node_modules/@expo/config-plugins": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-8.0.11.tgz", + "integrity": "sha512-oALE1HwnLFthrobAcC9ocnR9KXLzfWEjgIe4CPe+rDsfC6GDs8dGYCXfRFoCEzoLN4TGYs9RdZ8r0KoCcNrm2A==", + "license": "MIT", + "dependencies": { + "@expo/config-types": "^51.0.3", + "@expo/json-file": "~8.3.0", + "@expo/plist": "^0.1.0", + "@expo/sdk-runtime-versions": "^1.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.1", + "find-up": "~5.0.0", + "getenv": "^1.0.0", + "glob": "7.1.6", + "resolve-from": "^5.0.0", + "semver": "^7.5.4", + "slash": "^3.0.0", + "slugify": "^1.6.6", + "xcode": "^3.0.1", + "xml2js": "0.6.0" + } + }, + "node_modules/@expo/config-plugins/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/config-plugins/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/config-types": { + "version": "51.0.3", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-51.0.3.tgz", + "integrity": "sha512-hMfuq++b8VySb+m9uNNrlpbvGxYc8OcFCUX9yTmi9tlx6A4k8SDabWFBgmnr4ao3wEArvWrtUQIfQCVtPRdpKA==", + "license": "MIT" + }, + "node_modules/@expo/config/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/config/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/config/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/devcert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@expo/devcert/-/devcert-1.2.1.tgz", + "integrity": "sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA==", + "license": "MIT", + "dependencies": { + "@expo/sudo-prompt": "^9.3.1", + "debug": "^3.1.0" + } + }, + "node_modules/@expo/devcert/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@expo/env": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@expo/env/-/env-0.3.0.tgz", + "integrity": "sha512-OtB9XVHWaXidLbHvrVDeeXa09yvTl3+IQN884sO6PhIi2/StXfgSH/9zC7IvzrDB8kW3EBJ1PPLuCUJ2hxAT7Q==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "debug": "^4.3.4", + "dotenv": "~16.4.5", + "dotenv-expand": "~11.0.6", + "getenv": "^1.0.0" + } + }, + "node_modules/@expo/image-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.5.1.tgz", + "integrity": "sha512-U/GsFfFox88lXULmFJ9Shfl2aQGcwoKPF7fawSCLixIKtMCpsI+1r0h+5i0nQnmt9tHuzXZDL8+Dg1z6OhkI9A==", + "license": "MIT", + "dependencies": { + "@expo/spawn-async": "^1.7.2", + "chalk": "^4.0.0", + "fs-extra": "9.0.0", + "getenv": "^1.0.0", + "jimp-compact": "0.16.1", + "node-fetch": "^2.6.0", + "parse-png": "^2.1.0", + "resolve-from": "^5.0.0", + "semver": "^7.6.0", + "tempy": "0.3.0" + } + }, + "node_modules/@expo/image-utils/node_modules/crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/image-utils/node_modules/fs-extra": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/image-utils/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@expo/image-utils/node_modules/jsonfile/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@expo/image-utils/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/image-utils/node_modules/temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/image-utils/node_modules/tempy": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.3.0.tgz", + "integrity": "sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ==", + "license": "MIT", + "dependencies": { + "temp-dir": "^1.0.0", + "type-fest": "^0.3.1", + "unique-string": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@expo/image-utils/node_modules/type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=6" + } + }, + "node_modules/@expo/image-utils/node_modules/unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha512-ODgiYu03y5g76A1I9Gt0/chLCzQjvzDy7DsZGsLOE/1MrF6wriEskSncj1+/C58Xk/kPZDppSctDybCwOSaGAg==", + "license": "MIT", + "dependencies": { + "crypto-random-string": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/image-utils/node_modules/universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@expo/json-file": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.3.3.tgz", + "integrity": "sha512-eZ5dld9AD0PrVRiIWpRkm5aIoWBw3kAyd8VkuWEy92sEthBKDDDHAnK2a0dw0Eil6j7rK7lS/Qaq/Zzngv2h5A==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "~7.10.4", + "json5": "^2.2.2", + "write-file-atomic": "^2.3.0" + } + }, + "node_modules/@expo/json-file/node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@expo/metro-config": { + "version": "0.18.11", + "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-0.18.11.tgz", + "integrity": "sha512-/uOq55VbSf9yMbUO1BudkUM2SsGW1c5hr9BnhIqYqcsFv0Jp5D3DtJ4rljDKaUeNLbwr6m7pqIrkSMq5NrYf4Q==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.5", + "@babel/parser": "^7.20.0", + "@babel/types": "^7.20.0", + "@expo/config": "~9.0.0-beta.0", + "@expo/env": "~0.3.0", + "@expo/json-file": "~8.3.0", + "@expo/spawn-async": "^1.7.2", + "chalk": "^4.1.0", + "debug": "^4.3.2", + "find-yarn-workspace-root": "~2.0.0", + "fs-extra": "^9.1.0", + "getenv": "^1.0.0", + "glob": "^7.2.3", + "jsc-safe-url": "^0.2.4", + "lightningcss": "~1.19.0", + "postcss": "~8.4.32", + "resolve-from": "^5.0.0" + } + }, + "node_modules/@expo/metro-config/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/metro-config/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@expo/metro-config/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@expo/metro-runtime": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@expo/metro-runtime/-/metro-runtime-3.2.3.tgz", + "integrity": "sha512-v5ji+fAGi7B9YavrxvekuF8gXEV/5fz0+PhaED5AaFDnbGB4IJIbpaiqK9nqZV1axjGZNQSw6Q8TsnFetCR3bQ==", + "license": "MIT", + "peerDependencies": { + "react-native": "*" + } + }, + "node_modules/@expo/osascript": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.7.0.tgz", + "integrity": "sha512-wKIXL8UtbuX4KwavPasIW3CUcgTbYfjzLcgUhjyKUAYDEqMaf6gmU1bqz3ffBPTokmX+G8/vFG1ZuI9etQWukA==", + "license": "MIT", + "dependencies": { + "@expo/spawn-async": "^1.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/package-manager": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.13.0.tgz", + "integrity": "sha512-s3W3eZafJDEyVL7W/jxj2Nz3eONKxSCU604S5xj8ijrVaRz83x0DnZznLf/UXQEI1w+FyibH68nHeQyk767b1A==", + "license": "MIT", + "dependencies": { + "@expo/json-file": "^11.0.0", + "@expo/spawn-async": "^1.8.0", + "chalk": "^4.0.0", + "npm-package-arg": "^11.0.0", + "ora": "^3.4.0", + "resolve-workspace-root": "^2.0.0" + } + }, + "node_modules/@expo/package-manager/node_modules/@expo/json-file": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-11.0.0.tgz", + "integrity": "sha512-pHJCETqFL5x5BzNV6cEPwjwuECgGmnl0bNmfHIJ6LM1tlh2eVXi5HEdit3zby/JO/B8Otk5cgcqtJXgvvUat3A==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.20.0", + "json5": "^2.2.3" + } + }, + "node_modules/@expo/package-manager/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@expo/package-manager/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/@expo/package-manager/node_modules/npm-package-arg": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz", + "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==", + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@expo/package-manager/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/package-manager/node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@expo/plist": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.1.3.tgz", + "integrity": "sha512-GW/7hVlAylYg1tUrEASclw1MMk9FP4ZwyFAY/SUTJIhPDQHtfOlXREyWV3hhrHdX/K+pS73GNgdfT6E/e+kBbg==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "~0.7.7", + "base64-js": "^1.2.3", + "xmlbuilder": "^14.0.0" + } + }, + "node_modules/@expo/prebuild-config": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-7.0.9.tgz", + "integrity": "sha512-9i6Cg7jInpnGEHN0jxnW0P+0BexnePiBzmbUvzSbRXpdXihYUX2AKMu73jgzxn5P1hXOSkzNS7umaY+BZ+aBag==", + "license": "MIT", + "dependencies": { + "@expo/config": "~9.0.0-beta.0", + "@expo/config-plugins": "~8.0.8", + "@expo/config-types": "^51.0.3", + "@expo/image-utils": "^0.5.0", + "@expo/json-file": "^8.3.0", + "@react-native/normalize-colors": "0.74.85", + "debug": "^4.3.1", + "fs-extra": "^9.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.6.0", + "xml2js": "0.6.0" + }, + "peerDependencies": { + "expo-modules-autolinking": ">=0.8.1" + } + }, + "node_modules/@expo/prebuild-config/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/prebuild-config/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@expo/prebuild-config/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@expo/prebuild-config/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@expo/rudder-sdk-node": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@expo/rudder-sdk-node/-/rudder-sdk-node-1.1.1.tgz", + "integrity": "sha512-uy/hS/awclDJ1S88w9UGpc6Nm9XnNUjzOAAib1A3PVAnGQIwebg8DpFqOthFBTlZxeuV/BKbZ5jmTbtNZkp1WQ==", + "license": "MIT", + "dependencies": { + "@expo/bunyan": "^4.0.0", + "@segment/loosely-validate-event": "^2.0.0", + "fetch-retry": "^4.1.1", + "md5": "^2.2.1", + "node-fetch": "^2.6.1", + "remove-trailing-slash": "^0.1.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/sdk-runtime-versions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz", + "integrity": "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==", + "license": "MIT" + }, + "node_modules/@expo/server": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@expo/server/-/server-0.4.4.tgz", + "integrity": "sha512-q9ADBzMN5rZ/fgQ2mz5YIJuZ8gelQlhG2CQqToD+UvBLZvbaHCNxTTSs2KI1LzJvAaW5CWgWMatGvGF6iUQ0LA==", + "license": "MIT", + "dependencies": { + "@remix-run/node": "^2.7.2", + "abort-controller": "^3.0.0", + "debug": "^4.3.4", + "source-map-support": "~0.5.21" + } + }, + "node_modules/@expo/spawn-async": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.8.0.tgz", + "integrity": "sha512-eb9xxd/LbuEGSdua4NumCu/McVB9EM+F/JxB9pWgnERw4HQ9XyTNH1KapG6oqLWR8TuRK2LQfzJlmNi94CVobw==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.6" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/sudo-prompt": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@expo/sudo-prompt/-/sudo-prompt-9.3.2.tgz", + "integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==", + "license": "MIT" + }, + "node_modules/@expo/vector-icons": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-14.1.0.tgz", + "integrity": "sha512-7T09UE9h8QDTsUeMGymB4i+iqvtEeaO5VvUjryFB4tugDTG/bkzViWA74hm5pfjjDEhYMXWaX112mcvhccmIwQ==", + "license": "MIT", + "peerDependencies": { + "expo-font": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/@expo/xcpretty": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@expo/xcpretty/-/xcpretty-4.4.4.tgz", + "integrity": "sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/code-frame": "^7.20.0", + "chalk": "^4.1.0", + "js-yaml": "^4.1.0" + }, + "bin": { + "excpretty": "build/cli.js" + } + }, + "node_modules/@expo/xcpretty/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/@expo/xcpretty/node_modules/js-yaml": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "license": "MIT", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/create-cache-key-function/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/create-cache-key-function/node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@jest/create-cache-key-function/node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment/node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@jest/environment/node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@jest/fake-timers/node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", + "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz", + "integrity": "sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.1.tgz", + "integrity": "sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@react-native-async-storage/async-storage": { + "version": "1.23.1", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.23.1.tgz", + "integrity": "sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA==", + "license": "MIT", + "dependencies": { + "merge-options": "^3.0.4" + }, + "peerDependencies": { + "react-native": "^0.0.0-0 || >=0.60 <1.0" + } + }, + "node_modules/@react-native-community/cli": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-13.6.9.tgz", + "integrity": "sha512-hFJL4cgLPxncJJd/epQ4dHnMg5Jy/7Q56jFvA3MHViuKpzzfTCJCB+pGY54maZbtym53UJON9WTGpM3S81UfjQ==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-clean": "13.6.9", + "@react-native-community/cli-config": "13.6.9", + "@react-native-community/cli-debugger-ui": "13.6.9", + "@react-native-community/cli-doctor": "13.6.9", + "@react-native-community/cli-hermes": "13.6.9", + "@react-native-community/cli-server-api": "13.6.9", + "@react-native-community/cli-tools": "13.6.9", + "@react-native-community/cli-types": "13.6.9", + "chalk": "^4.1.2", + "commander": "^9.4.1", + "deepmerge": "^4.3.0", + "execa": "^5.0.0", + "find-up": "^4.1.0", + "fs-extra": "^8.1.0", + "graceful-fs": "^4.1.3", + "prompts": "^2.4.2", + "semver": "^7.5.2" + }, + "bin": { + "rnc-cli": "build/bin.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native-community/cli-clean": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-13.6.9.tgz", + "integrity": "sha512-7Dj5+4p9JggxuVNOjPbduZBAP1SUgNhLKVw5noBUzT/3ZpUZkDM+RCSwyoyg8xKWoE4OrdUAXwAFlMcFDPKykA==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "13.6.9", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-glob": "^3.3.2" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-clean/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-config": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-13.6.9.tgz", + "integrity": "sha512-rFfVBcNojcMm+KKHE/xqpqXg8HoKl4EC7bFHUrahMJ+y/tZll55+oX/PGG37rzB8QzP2UbMQ19DYQKC1G7kXeg==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "13.6.9", + "chalk": "^4.1.2", + "cosmiconfig": "^5.1.0", + "deepmerge": "^4.3.0", + "fast-glob": "^3.3.2", + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli-debugger-ui": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-13.6.9.tgz", + "integrity": "sha512-TkN7IdFmGPPvTpAo3nCAH9uwGCPxWBEAwpqEZDrq0NWllI7Tdie8vDpGdrcuCcKalmhq6OYnkXzeBah7O1Ztpw==", + "license": "MIT", + "dependencies": { + "serve-static": "^1.13.1" + } + }, + "node_modules/@react-native-community/cli-doctor": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-13.6.9.tgz", + "integrity": "sha512-5quFaLdWFQB+677GXh5dGU9I5eg2z6Vg4jOX9vKnc9IffwyIFAyJfCZHrxLSRPDGNXD7biDQUdoezXYGwb6P/A==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-config": "13.6.9", + "@react-native-community/cli-platform-android": "13.6.9", + "@react-native-community/cli-platform-apple": "13.6.9", + "@react-native-community/cli-platform-ios": "13.6.9", + "@react-native-community/cli-tools": "13.6.9", + "chalk": "^4.1.2", + "command-exists": "^1.2.8", + "deepmerge": "^4.3.0", + "envinfo": "^7.10.0", + "execa": "^5.0.0", + "hermes-profile-transformer": "^0.0.6", + "node-stream-zip": "^1.9.1", + "ora": "^5.4.1", + "semver": "^7.5.2", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1", + "yaml": "^2.2.1" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/ora/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli-hermes": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-13.6.9.tgz", + "integrity": "sha512-GvwiwgvFw4Ws+krg2+gYj8sR3g05evmNjAHkKIKMkDTJjZ8EdyxbkifRUs1ZCq3TMZy2oeblZBXCJVOH4W7ZbA==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-platform-android": "13.6.9", + "@react-native-community/cli-tools": "13.6.9", + "chalk": "^4.1.2", + "hermes-profile-transformer": "^0.0.6" + } + }, + "node_modules/@react-native-community/cli-platform-android": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-13.6.9.tgz", + "integrity": "sha512-9KsYGdr08QhdvT3Ht7e8phQB3gDX9Fs427NJe0xnoBh+PDPTI2BD5ks5ttsH8CzEw8/P6H8tJCHq6hf2nxd9cw==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "13.6.9", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-glob": "^3.3.2", + "fast-xml-parser": "^4.2.4", + "logkitty": "^0.7.1" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-platform-android/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-apple": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-apple/-/cli-platform-apple-13.6.9.tgz", + "integrity": "sha512-KoeIHfhxMhKXZPXmhQdl6EE+jGKWwoO9jUVWgBvibpVmsNjo7woaG/tfJMEWfWF3najX1EkQAoJWpCDBMYWtlA==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "13.6.9", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-glob": "^3.3.2", + "fast-xml-parser": "^4.0.12", + "ora": "^5.4.1" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-platform-apple/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-platform-ios": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-13.6.9.tgz", + "integrity": "sha512-CiUcHlGs8vE0CAB4oi1f+dzniqfGuhWPNrDvae2nm8dewlahTBwIcK5CawyGezjcJoeQhjBflh9vloska+nlnw==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-platform-apple": "13.6.9" + } + }, + "node_modules/@react-native-community/cli-server-api": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-13.6.9.tgz", + "integrity": "sha512-W8FSlCPWymO+tlQfM3E0JmM8Oei5HZsIk5S0COOl0MRi8h0NmHI4WSTF2GCfbFZkcr2VI/fRsocoN8Au4EZAug==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-debugger-ui": "13.6.9", + "@react-native-community/cli-tools": "13.6.9", + "compression": "^1.7.1", + "connect": "^3.6.5", + "errorhandler": "^1.5.1", + "nocache": "^3.0.1", + "pretty-format": "^26.6.2", + "serve-static": "^1.13.1", + "ws": "^6.2.2" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@types/yargs": { + "version": "15.0.20", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.20.tgz", + "integrity": "sha512-KIkX+/GgfFitlASYCGoSF+T4XRXhOubJLhkLVtSfsRTe9jWMmuM2g28zQ41BtPTG7TRBb2xHW+LCNVE9QR/vsg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "license": "MIT", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/@react-native-community/cli-server-api/node_modules/ws": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.4.tgz", + "integrity": "sha512-PNIUUyLI5YpkJZj60YBzX1o0ByQ4ovvfmq9N/Kig/PAYbVlGyz4R6G0SEWrD0O9acc0sT2+IdMBVLFv8FSi0Nw==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native-community/cli-tools": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-13.6.9.tgz", + "integrity": "sha512-OXaSjoN0mZVw3nrAwcY1PC0uMfyTd9fz7Cy06dh+EJc+h0wikABsVRzV8cIOPrVV+PPEEXE0DBrH20T2puZzgQ==", + "license": "MIT", + "dependencies": { + "appdirsjs": "^1.2.4", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "find-up": "^5.0.0", + "mime": "^2.4.1", + "node-fetch": "^2.6.0", + "open": "^6.2.0", + "ora": "^5.4.1", + "semver": "^7.5.2", + "shell-quote": "^1.7.3", + "sudo-prompt": "^9.0.0" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "license": "MIT", + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-types": { + "version": "13.6.9", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-13.6.9.tgz", + "integrity": "sha512-RLxDppvRxXfs3hxceW/mShi+6o5yS+kFPnPqZTaMKKR5aSg7LwDpLQW4K2D22irEG8e6RKDkZUeH9aL3vO2O0w==", + "license": "MIT", + "dependencies": { + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/@react-native-community/cli/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native-community/cli/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.74.87.tgz", + "integrity": "sha512-1XmRhqQchN+pXPKEKYdpJlwESxVomJOxtEnIkbo7GAlaN2sym84fHEGDXAjLilih5GVPpcpSmFzTy8jx3LtaFg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.74.87.tgz", + "integrity": "sha512-+vJYpMnENFrwtgvDfUj+CtVJRJuUnzAUYT0/Pb68Sq9RfcZ5xdcCuUgyf7JO+akW2VTBoJY427wkcxU30qrWWw==", + "license": "MIT", + "dependencies": { + "@react-native/codegen": "0.74.87" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-preset": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.74.87.tgz", + "integrity": "sha512-hyKpfqzN2nxZmYYJ0tQIHG99FQO0OWXp/gVggAfEUgiT+yNKas1C60LuofUsK7cd+2o9jrpqgqW4WzEDZoBlTg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/plugin-proposal-async-generator-functions": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.18.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", + "@babel/plugin-proposal-numeric-separator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.20.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.18.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.20.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.20.0", + "@babel/plugin-transform-flow-strip-types": "^7.20.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "@react-native/babel-plugin-codegen": "0.74.87", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.74.87.tgz", + "integrity": "sha512-GMSYDiD+86zLKgMMgz9z0k6FxmRn+z6cimYZKkucW4soGbxWsbjUAZoZ56sJwt2FJ3XVRgXCrnOCgXoH/Bkhcg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.0", + "glob": "^7.1.1", + "hermes-parser": "0.19.1", + "invariant": "^2.2.4", + "jscodeshift": "^0.14.0", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/@react-native/codegen/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/@react-native/community-cli-plugin": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.74.87.tgz", + "integrity": "sha512-EgJG9lSr8x3X67dHQKQvU6EkO+3ksVlJHYIVv6U/AmW9dN80BEFxgYbSJ7icXS4wri7m4kHdgeq2PQ7/3vvrTQ==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-server-api": "13.6.9", + "@react-native-community/cli-tools": "13.6.9", + "@react-native/dev-middleware": "0.74.87", + "@react-native/metro-babel-transformer": "0.74.87", + "chalk": "^4.0.0", + "execa": "^5.1.1", + "metro": "^0.80.3", + "metro-config": "^0.80.3", + "metro-core": "^0.80.3", + "node-fetch": "^2.2.0", + "querystring": "^0.2.1", + "readline": "^1.3.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/@react-native/debugger-frontend": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.74.87.tgz", + "integrity": "sha512-MN95DJLYTv4EqJc+9JajA3AJZSBYJz2QEJ3uWlHrOky2vKrbbRVaW1ityTmaZa2OXIvNc6CZwSRSE7xCoHbXhQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/@react-native/dev-middleware": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.74.87.tgz", + "integrity": "sha512-7TmZ3hTHwooYgIHqc/z87BMe1ryrIqAUi+AF7vsD+EHCGxHFdMjSpf1BZ2SUPXuLnF2cTiTfV2RwhbPzx0tYIA==", + "license": "MIT", + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.74.87", + "@rnx-kit/chromium-edge-launcher": "^1.0.0", + "chrome-launcher": "^0.15.2", + "connect": "^3.6.5", + "debug": "^2.2.0", + "node-fetch": "^2.2.0", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "selfsigned": "^2.4.1", + "serve-static": "^1.13.1", + "temp-dir": "^2.0.0", + "ws": "^6.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/@react-native/community-cli-plugin/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native/community-cli-plugin/node_modules/ws": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.4.tgz", + "integrity": "sha512-PNIUUyLI5YpkJZj60YBzX1o0ByQ4ovvfmq9N/Kig/PAYbVlGyz4R6G0SEWrD0O9acc0sT2+IdMBVLFv8FSi0Nw==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.74.85", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.74.85.tgz", + "integrity": "sha512-gUIhhpsYLUTYWlWw4vGztyHaX/kNlgVspSvKe2XaPA7o3jYKUoNLc3Ov7u70u/MBWfKdcEffWq44eSe3j3s5JQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware": { + "version": "0.74.85", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.74.85.tgz", + "integrity": "sha512-BRmgCK5vnMmHaKRO+h8PKJmHHH3E6JFuerrcfE3wG2eZ1bcSr+QTu8DAlpxsDWvJvHpCi8tRJGauxd+Ssj/c7w==", + "license": "MIT", + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.74.85", + "@rnx-kit/chromium-edge-launcher": "^1.0.0", + "chrome-launcher": "^0.15.2", + "connect": "^3.6.5", + "debug": "^2.2.0", + "node-fetch": "^2.2.0", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "selfsigned": "^2.4.1", + "serve-static": "^1.13.1", + "temp-dir": "^2.0.0", + "ws": "^6.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/@react-native/dev-middleware/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ws": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.4.tgz", + "integrity": "sha512-PNIUUyLI5YpkJZj60YBzX1o0ByQ4ovvfmq9N/Kig/PAYbVlGyz4R6G0SEWrD0O9acc0sT2+IdMBVLFv8FSi0Nw==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.74.87.tgz", + "integrity": "sha512-T+VX0N1qP+U9V4oAtn7FTX7pfsoVkd1ocyw9swYXgJqU2fK7hC9famW7b3s3ZiufPGPr1VPJe2TVGtSopBjL6A==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.74.87.tgz", + "integrity": "sha512-M5Evdn76CuVEF0GsaXiGi95CBZ4IWubHqwXxV9vG9CC9kq0PSkoM2Pn7Lx7dgyp4vT7ccJ8a3IwHbe+5KJRnpw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/metro-babel-transformer": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.74.87.tgz", + "integrity": "sha512-UsJCO24sNax2NSPBmV1zLEVVNkS88kcgAiYrZHtYSwSjpl4WZ656tIeedBfiySdJ94Hr3kQmBYLipV5zk0NI1A==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@react-native/babel-preset": "0.74.87", + "hermes-parser": "0.19.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.74.85", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.74.85.tgz", + "integrity": "sha512-pcE4i0X7y3hsAE0SpIl7t6dUc0B0NZLd1yv7ssm4FrLhWG+CGyIq4eFDXpmPU1XHmL5PPySxTAjEMiwv6tAmOw==", + "license": "MIT" + }, + "node_modules/@react-navigation/bottom-tabs": { + "version": "6.5.20", + "resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.20.tgz", + "integrity": "sha512-ow6Z06iS4VqBO8d7FP+HsGjJLWt2xTWIvuWjpoCvsM/uQXzCRDIjBv9HaKcXbF0yTW7IMir0oDAbU5PFzEDdgA==", + "deprecated": "This version is no longer supported", + "license": "MIT", + "dependencies": { + "@react-navigation/elements": "^1.3.30", + "color": "^4.2.3", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, + "node_modules/@react-navigation/core": { + "version": "6.4.17", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.17.tgz", + "integrity": "sha512-Nd76EpomzChWAosGqWOYE3ItayhDzIEzzZsT7PfGcRFDgW5miHV2t4MZcq9YIK4tzxZjVVpYbIynOOQQd1e0Cg==", + "deprecated": "This version is no longer supported", + "license": "MIT", + "dependencies": { + "@react-navigation/routers": "^6.1.9", + "escape-string-regexp": "^4.0.0", + "nanoid": "^3.1.23", + "query-string": "^7.1.3", + "react-is": "^16.13.0", + "use-latest-callback": "^0.2.1" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/@react-navigation/elements": { + "version": "1.3.31", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.31.tgz", + "integrity": "sha512-bUzP4Awlljx5RKEExw8WYtif8EuQni2glDaieYROKTnaxsu9kEIA515sXQgUDZU4Ob12VoL7+z70uO3qrlfXcQ==", + "deprecated": "This version is no longer supported", + "license": "MIT", + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-safe-area-context": ">= 3.0.0" + } + }, + "node_modules/@react-navigation/native": { + "version": "6.1.18", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.18.tgz", + "integrity": "sha512-mIT9MiL/vMm4eirLcmw2h6h/Nm5FICtnYSdohq4vTLA2FF/6PNhByM7s8ffqoVfE5L0uAa6Xda1B7oddolUiGg==", + "deprecated": "This version is no longer supported", + "license": "MIT", + "peer": true, + "dependencies": { + "@react-navigation/core": "^6.4.17", + "escape-string-regexp": "^4.0.0", + "fast-deep-equal": "^3.1.3", + "nanoid": "^3.1.23" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/@react-navigation/native-stack": { + "version": "6.9.26", + "resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.26.tgz", + "integrity": "sha512-++dueQ+FDj2XkZ902DVrK79ub1vp19nSdAZWxKRgd6+Bc0Niiesua6rMCqymYOVaYh+dagwkA9r00bpt/U5WLw==", + "license": "MIT", + "dependencies": { + "@react-navigation/elements": "^1.3.30", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, + "node_modules/@react-navigation/routers": { + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.9.tgz", + "integrity": "sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==", + "deprecated": "This version is no longer supported", + "license": "MIT", + "dependencies": { + "nanoid": "^3.1.23" + } + }, + "node_modules/@remix-run/node": { + "version": "2.17.5", + "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.17.5.tgz", + "integrity": "sha512-CwOUCDJqh9o8r/n5N1l+vz4Jh7DFU52/jo7MN56+OL9gM+14aQKdq1aLAh+4V6GuI/qtki9PPk02GmULimmDkw==", + "license": "MIT", + "dependencies": { + "@remix-run/server-runtime": "2.17.5", + "@remix-run/web-fetch": "^4.4.2", + "@web3-storage/multipart-parser": "^1.0.0", + "cookie-signature": "^1.1.0", + "source-map-support": "^0.5.21", + "stream-slice": "^0.1.2", + "undici": "^6.21.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@remix-run/router": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.3.tgz", + "integrity": "sha512-4An71tdz9X8+3sI4Qqqd2LWd9vS39J7sqd9EU4Scw7TJE/qB10Flv/UuqbPVgfQV9XoK8Np6jNquZitnZq5i+Q==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@remix-run/server-runtime": { + "version": "2.17.5", + "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.17.5.tgz", + "integrity": "sha512-SyJ5n2pQyo4ERGvjjLvL2PpRWBzlC2qzO5KkkOE2ygOiNcgOu9WQnnom9GI8KgsTRCO8JnIeLHFRcmxZnVBjfw==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3", + "@types/cookie": "^0.6.0", + "@web3-storage/multipart-parser": "^1.0.0", + "cookie": "^0.7.2", + "set-cookie-parser": "^2.4.8", + "source-map": "^0.7.3", + "turbo-stream": "2.4.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@remix-run/web-blob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@remix-run/web-blob/-/web-blob-3.1.0.tgz", + "integrity": "sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==", + "license": "MIT", + "dependencies": { + "@remix-run/web-stream": "^1.1.0", + "web-encoding": "1.1.5" + } + }, + "node_modules/@remix-run/web-fetch": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@remix-run/web-fetch/-/web-fetch-4.4.2.tgz", + "integrity": "sha512-jgKfzA713/4kAW/oZ4bC3MoLWyjModOVDjFPNseVqcJKSafgIscrYL9G50SurEYLswPuoU3HzSbO0jQCMYWHhA==", + "license": "MIT", + "dependencies": { + "@remix-run/web-blob": "^3.1.0", + "@remix-run/web-file": "^3.1.0", + "@remix-run/web-form-data": "^3.1.0", + "@remix-run/web-stream": "^1.1.0", + "@web3-storage/multipart-parser": "^1.0.0", + "abort-controller": "^3.0.0", + "data-uri-to-buffer": "^3.0.1", + "mrmime": "^1.0.0" + }, + "engines": { + "node": "^10.17 || >=12.3" + } + }, + "node_modules/@remix-run/web-file": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@remix-run/web-file/-/web-file-3.1.0.tgz", + "integrity": "sha512-dW2MNGwoiEYhlspOAXFBasmLeYshyAyhIdrlXBi06Duex5tDr3ut2LFKVj7tyHLmn8nnNwFf1BjNbkQpygC2aQ==", + "license": "MIT", + "dependencies": { + "@remix-run/web-blob": "^3.1.0" + } + }, + "node_modules/@remix-run/web-form-data": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@remix-run/web-form-data/-/web-form-data-3.1.0.tgz", + "integrity": "sha512-NdeohLMdrb+pHxMQ/Geuzdp0eqPbea+Ieo8M8Jx2lGC6TBHsgHzYcBvr0LyPdPVycNRDEpWpiDdCOdCryo3f9A==", + "license": "MIT", + "dependencies": { + "web-encoding": "1.1.5" + } + }, + "node_modules/@remix-run/web-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@remix-run/web-stream/-/web-stream-1.1.0.tgz", + "integrity": "sha512-KRJtwrjRV5Bb+pM7zxcTJkhIqWWSy+MYsIxHK+0m5atcznsf15YwUBWHWulZerV2+vvHH1Lp1DD7pw6qKW8SgA==", + "license": "MIT", + "dependencies": { + "web-streams-polyfill": "^3.1.1" + } + }, + "node_modules/@rnx-kit/chromium-edge-launcher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rnx-kit/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", + "integrity": "sha512-lzD84av1ZQhYUS+jsGqJiCMaJO2dn9u+RTT9n9q6D3SaKVwWqv+7AoRKqBu19bkwyE+iFRl1ymr40QS90jVFYg==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "^18.0.0", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=14.15" + } + }, + "node_modules/@segment/loosely-validate-event": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz", + "integrity": "sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw==", + "dependencies": { + "component-type": "^1.2.1", + "join-component": "^1.1.0" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "license": "MIT" + }, + "node_modules/@types/hammerjs": { + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.46.tgz", + "integrity": "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.2.79", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz", + "integrity": "sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "13.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", + "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@urql/core": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@urql/core/-/core-2.3.6.tgz", + "integrity": "sha512-PUxhtBh7/8167HJK6WqBv6Z0piuiaZHQGYbhwpNL9aIQmLROPEdaUYkY4wh45wPQXcTpnd11l0q3Pw+TI11pdw==", + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.0", + "wonka": "^4.0.14" + }, + "peerDependencies": { + "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@urql/exchange-retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@urql/exchange-retry/-/exchange-retry-0.3.0.tgz", + "integrity": "sha512-hHqer2mcdVC0eYnVNbWyi28AlGOPb2vjH3lP3/Bc8Lc8BjhMsDwFMm7WhoP5C1+cfbr/QJ6Er3H/L08wznXxfg==", + "license": "MIT", + "dependencies": { + "@urql/core": ">=2.3.1", + "wonka": "^4.0.14" + }, + "peerDependencies": { + "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/@web3-storage/multipart-parser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz", + "integrity": "sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==", + "license": "(Apache-2.0 AND MIT)" + }, + "node_modules/@xmldom/xmldom": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz", + "integrity": "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==", + "deprecated": "this version has critical issues, please update to the latest version", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "license": "(Unlicense OR Apache-2.0)", + "optional": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-fragments": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", + "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", + "license": "MIT", + "dependencies": { + "colorette": "^1.0.7", + "slice-ansi": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/appdirsjs": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz", + "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==", + "license": "MIT" + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, + "node_modules/ast-types": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", + "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "license": "MIT", + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-react-compiler": { + "version": "0.0.0-experimental-592953e-20240517", + "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-0.0.0-experimental-592953e-20240517.tgz", + "integrity": "sha512-OjG1SVaeQZaJrqkMFJatg8W/MTow8Ak5rx2SI0ETQBO1XvOk/XZGMbltNCPdFJLKghBYoBjC+Y3Ap/Xr7B01mA==", + "license": "MIT", + "dependencies": { + "@babel/generator": "7.2.0", + "@babel/types": "^7.19.0", + "chalk": "4", + "invariant": "^2.2.4", + "pretty-format": "^24", + "zod": "^3.22.4", + "zod-validation-error": "^2.1.0" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/@babel/generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", + "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.2.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-plugin-react-native-web": { + "version": "0.19.13", + "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.19.13.tgz", + "integrity": "sha512-4hHoto6xaN23LCyZgL9LJZc3olmAxd7b6jDzlZnKXAh4rRAbZRKNBJoOOdp46OBqgy+K0t0guTj5/mhA8inymQ==", + "license": "MIT" + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/babel-preset-expo": { + "version": "11.0.15", + "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-11.0.15.tgz", + "integrity": "sha512-rgiMTYwqIPULaO7iZdqyL7aAff9QLOX6OWUtLZBlOrOTreGY1yHah/5+l8MvI6NVc/8Zj5LY4Y5uMSnJIuzTLw==", + "license": "MIT", + "dependencies": { + "@babel/plugin-proposal-decorators": "^7.12.9", + "@babel/plugin-transform-export-namespace-from": "^7.22.11", + "@babel/plugin-transform-object-rest-spread": "^7.12.13", + "@babel/plugin-transform-parameters": "^7.22.15", + "@babel/preset-react": "^7.22.15", + "@babel/preset-typescript": "^7.23.0", + "@react-native/babel-preset": "0.74.87", + "babel-plugin-react-compiler": "0.0.0-experimental-592953e-20240517", + "babel-plugin-react-native-web": "~0.19.10", + "react-refresh": "^0.14.2" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.43", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.43.tgz", + "integrity": "sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/better-opn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", + "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", + "license": "MIT", + "dependencies": { + "open": "^8.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/bplist-creator": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.7.tgz", + "integrity": "sha512-xp/tcaV3T5PCiaY04mXga7o/TE+t95gqeLmADeBI1CvZtdWTbgBt3uLpvh4UWtenKeBhCV6oVxGk38yZr2uYEA==", + "license": "MIT", + "dependencies": { + "stream-buffers": "~2.2.0" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", + "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.6.tgz", + "integrity": "sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.10.42", + "caniuse-lite": "^1.0.30001803", + "electron-to-chromium": "^1.5.389", + "node-releases": "^2.0.51", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "license": "MIT", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "license": "MIT" + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", + "license": "MIT" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "18.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", + "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "license": "MIT", + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "license": "MIT", + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001805", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001805.tgz", + "integrity": "sha512-52noaS3DubycKSXaU30TwPGIp+POyQSUVa5jBEq3vkRkY0kjyb3LQgvhU6WGyCcyXqVLWO0Cw0Q6BSdD0kUfVA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "license": "MIT" + }, + "node_modules/component-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/component-type/-/component-type-1.2.2.tgz", + "integrity": "sha512-99VUHREHiN5cLeHm3YLq312p6v+HUEcwtLCAtelvUDI6+SH5g5Cr85oNR2S1o6ywzL0ykMbuwLzM2ANocjEOIA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/core-js-compat": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "license": "MIT", + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/css-in-js-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", + "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", + "license": "MIT", + "dependencies": { + "hyphenate-style-name": "^1.0.3" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/dag-map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dag-map/-/dag-map-1.0.2.tgz", + "integrity": "sha512-+LSAiGFwQ9dRnRdOeaj7g47ZFJcOUPukAP8J3A3fuZ1g9Y44BG+P1sgApjLXTQPOzC4+7S9Wr8kXsfpINM4jpw==", + "license": "MIT" + }, + "node_modules/data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "license": "BSD-2-Clause", + "dependencies": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "license": "MIT", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==", + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "license": "Apache-2.0", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.389", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.389.tgz", + "integrity": "sha512-cEto7aeOqBfU1D+c5py5pE+ooscKE75JifxLBdFUZsqAxRS6y7kebtxAZvICszSl05gPjYHDTjY+lXpyGvpJbg==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-editor": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/env-editor/-/env-editor-0.4.2.tgz", + "integrity": "sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/envinfo": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.21.0.tgz", + "integrity": "sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==", + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/errorhandler": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.2.tgz", + "integrity": "sha512-kNAL7hESndBCrWwS72QyV3IVOTrVmj9D062FV5BQswNL5zEdeRmz/WJFyh6Aj/plvvSOrzddkxW57HgkZcR9Fw==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "escape-html": "~1.0.3" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "license": "MIT", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/expo": { + "version": "51.0.39", + "resolved": "https://registry.npmjs.org/expo/-/expo-51.0.39.tgz", + "integrity": "sha512-Cs/9xopyzJrpXWbyVUZnr37rprdFJorRgfSp6cdBfvbjxZeKnw2MEu7wJwV/s626i5lZTPGjZPHUF9uQvt51cg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.20.0", + "@expo/cli": "0.18.31", + "@expo/config": "9.0.4", + "@expo/config-plugins": "8.0.11", + "@expo/metro-config": "0.18.11", + "@expo/vector-icons": "^14.0.3", + "babel-preset-expo": "~11.0.15", + "expo-asset": "~10.0.10", + "expo-file-system": "~17.0.1", + "expo-font": "~12.0.10", + "expo-keep-awake": "~13.0.2", + "expo-modules-autolinking": "1.11.3", + "expo-modules-core": "1.12.26", + "fbemitter": "^3.0.0", + "whatwg-url-without-unicode": "8.0.0-3" + }, + "bin": { + "expo": "bin/cli" + } + }, + "node_modules/expo-asset": { + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-10.0.10.tgz", + "integrity": "sha512-0qoTIihB79k+wGus9wy0JMKq7DdenziVx3iUkGvMAy2azscSgWH6bd2gJ9CGnhC6JRd3qTMFBL0ou/fx7WZl7A==", + "license": "MIT", + "dependencies": { + "expo-constants": "~16.0.0", + "invariant": "^2.2.4", + "md5-file": "^3.2.3" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-constants": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-16.0.2.tgz", + "integrity": "sha512-9tNY3OVO0jfiMzl7ngb6IOyR5VFzNoN5OOazUWoeGfmMqVB5kltTemRvKraK9JRbBKIw+SOYLEmF0sEqgFZ6OQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@expo/config": "~9.0.0", + "@expo/env": "~0.3.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-file-system": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-17.0.1.tgz", + "integrity": "sha512-dYpnZJqTGj6HCYJyXAgpFkQWsiCH3HY1ek2cFZVHFoEc5tLz9gmdEgTF6nFHurvmvfmXqxi7a5CXyVm0aFYJBw==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-font": { + "version": "12.0.10", + "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-12.0.10.tgz", + "integrity": "sha512-Q1i2NuYri3jy32zdnBaHHCya1wH1yMAsI+3CCmj9zlQzlhsS9Bdwcj2W3c5eU5FvH2hsNQy4O+O1NnM6o/pDaQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "fontfaceobserver": "^2.1.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-image-loader": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-4.7.0.tgz", + "integrity": "sha512-cx+MxxsAMGl9AiWnQUzrkJMJH4eNOGlu7XkLGnAXSJrRoIiciGaKqzeaD326IyCTV+Z1fXvIliSgNW+DscvD8g==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-image-picker": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-15.1.0.tgz", + "integrity": "sha512-6cE10S7d0qG7+pcHtsYukRKuFL44ssOM0/v+5JIBzRwxpIgGA6qokr8PxasFEpxOA9NpN0gwry33jmq1qLXJTg==", + "license": "MIT", + "dependencies": { + "expo-image-loader": "~4.7.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-keep-awake": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-13.0.2.tgz", + "integrity": "sha512-kKiwkVg/bY0AJ5q1Pxnm/GvpeB6hbNJhcFsoOWDh2NlpibhCLaHL826KHUM+WsnJRbVRxJ+K9vbPRHEMvFpVyw==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-linking": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-6.3.1.tgz", + "integrity": "sha512-xuZCntSBGWCD/95iZ+mTUGTwHdy8Sx+immCqbUBxdvZ2TN61P02kKg7SaLS8A4a/hLrSCwrg5tMMwu5wfKr35g==", + "license": "MIT", + "peer": true, + "dependencies": { + "expo-constants": "~16.0.0", + "invariant": "^2.2.4" + } + }, + "node_modules/expo-modules-autolinking": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.11.3.tgz", + "integrity": "sha512-oYh8EZEvYF5TYppxEKUTTJmbr8j7eRRnrIxzZtMvxLTXoujThVPMFS/cbnSnf2bFm1lq50TdDNABhmEi7z0ngQ==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "commander": "^7.2.0", + "fast-glob": "^3.2.5", + "find-up": "^5.0.0", + "fs-extra": "^9.1.0", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0" + }, + "bin": { + "expo-modules-autolinking": "bin/expo-modules-autolinking.js" + } + }, + "node_modules/expo-modules-autolinking/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/expo-modules-autolinking/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/expo-modules-autolinking/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/expo-modules-core": { + "version": "1.12.26", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.12.26.tgz", + "integrity": "sha512-y8yDWjOi+rQRdO+HY+LnUlz8qzHerUaw/LUjKPU/mX8PRXP4UUPEEp5fjAwBU44xjNmYSHWZDwet4IBBE+yQUA==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4" + } + }, + "node_modules/expo-router": { + "version": "3.5.24", + "resolved": "https://registry.npmjs.org/expo-router/-/expo-router-3.5.24.tgz", + "integrity": "sha512-wFi+PIUrOntF5cgg0PgBMlkxEZlWedIv5dWnPFEzN6Tr3A3bpsqdDLgOEIwvwd+pxn5DLzykTmg9EkQ1pPGspw==", + "license": "MIT", + "dependencies": { + "@expo/metro-runtime": "3.2.3", + "@expo/server": "^0.4.0", + "@radix-ui/react-slot": "1.0.1", + "@react-navigation/bottom-tabs": "~6.5.7", + "@react-navigation/native": "~6.1.6", + "@react-navigation/native-stack": "~6.9.12", + "expo-splash-screen": "0.27.7", + "react-native-helmet-async": "2.0.4", + "schema-utils": "^4.0.1" + }, + "peerDependencies": { + "@react-navigation/drawer": "^6.5.8", + "expo": "*", + "expo-constants": "*", + "expo-linking": "*", + "expo-status-bar": "*", + "react-native-reanimated": "*", + "react-native-safe-area-context": "*", + "react-native-screens": "*" + }, + "peerDependenciesMeta": { + "@react-navigation/drawer": { + "optional": true + }, + "@testing-library/jest-native": { + "optional": true + }, + "react-native-reanimated": { + "optional": true + } + } + }, + "node_modules/expo-secure-store": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/expo-secure-store/-/expo-secure-store-13.0.2.tgz", + "integrity": "sha512-3QYgoneo8p8yeeBPBiAfokNNc2xq6+n8+Ob4fAlErEcf4H7Y72LH+K/dx0nQyWau2ZKZUXBxyyfuHFyVKrEVLg==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-splash-screen": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-0.27.7.tgz", + "integrity": "sha512-s+eGcG185878nixlrjhhLD6UDYrvoqBUaBkIEozBVWFg3pkdsKpONPiUAco4XR3h7I/9ODq4quN28RJLFO+s0Q==", + "license": "MIT", + "dependencies": { + "@expo/prebuild-config": "7.0.9" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-status-bar": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.12.1.tgz", + "integrity": "sha512-/t3xdbS8KB0prj5KG5w7z+wZPFlPtkgs95BsmrP/E7Q0xHXTcDcQ6Cu2FkFuRM+PKTb17cJDnLkawyS5vDLxMA==", + "license": "MIT", + "peer": true + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "license": "Apache-2.0" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-loops": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.4.tgz", + "integrity": "sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", + "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fast-xml-parser": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.7.tgz", + "integrity": "sha512-a6Qh1RMCNbSrU1+sAyAAZH3rTe+OaWJbNZIq0S+ifZciUUOQtlVxBJwoTUE2bYhysmG/RYyI5WJFIKdBahJdrQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fbemitter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-3.0.0.tgz", + "integrity": "sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==", + "license": "BSD-3-Clause", + "dependencies": { + "fbjs": "^3.0.0" + } + }, + "node_modules/fbjs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", + "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", + "license": "MIT", + "dependencies": { + "cross-fetch": "^3.1.5", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^1.0.35" + } + }, + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", + "license": "MIT" + }, + "node_modules/fetch-retry": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-4.1.1.tgz", + "integrity": "sha512-e6eB7zN6UBSwGVwrbWVH+gdLnkW9WwHhmq2YDK1Sh30pzx1onRVGBvogTlUeWxwTa+L86NYdo4hFkh7O8ZjSnA==", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, + "node_modules/flow-enums-runtime": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", + "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "license": "MIT" + }, + "node_modules/flow-estree": { + "version": "0.322.0", + "resolved": "https://registry.npmjs.org/flow-estree/-/flow-estree-0.322.0.tgz", + "integrity": "sha512-v7wiiFWSKbJ1HGVCRKhxl+6pQWTQV6P4c7XEfKjVlH71YkgQyJCq0AG5dhJDD/3/SkJgX/F9lvAj2rbrFzArdQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/flow-parser": { + "version": "0.322.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.322.0.tgz", + "integrity": "sha512-Qfd8N4sSuWmlf1qk5M60fi8JrvhNvj9fbwMsRkcnm3UhLYukkbm2CFkAhiTD3n4RVXb6TuCHFCp78TMXpO0zcA==", + "license": "MIT", + "dependencies": { + "flow-estree": "0.322.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/fontfaceobserver": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz", + "integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==", + "license": "BSD-2-Clause" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.5.tgz", + "integrity": "sha512-j23EibVLnp4zNXGW7LjryXYa2X6U/M96yoOX+ybZxwkYajdxRNEqYY3zhh7y0i6kfISKS2jr+EJq1YTUDEv5+w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/freeport-async": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz", + "integrity": "sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getenv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/getenv/-/getenv-1.0.0.tgz", + "integrity": "sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphql": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", + "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/graphql-tag": { + "version": "2.12.7", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.7.tgz", + "integrity": "sha512-xnE/NFzy+0eIesvAsREJZ284zTl/wYuBAvpsFSDhRGRdRHdnE90M21Q3xAWyYInb0J756c6x0pIQ62+vtvOs1Q==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.19.1.tgz", + "integrity": "sha512-daLGV3Q2MKk8w4evNMKwS8zBE/rcpA800nu1Q5kM08IKijoSnPe9Uo1iIxzPKRkn95IxxsgBMPeYHt3VG4ej2g==", + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.19.1.tgz", + "integrity": "sha512-Vp+bXzxYJWrpEuJ/vXxUsLnt0+y4q9zyi4zUlkLqD8FKv4LjIfOvP69R/9Lty3dCyKh0E2BU7Eypqr63/rKT/A==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.19.1" + } + }, + "node_modules/hermes-profile-transformer": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz", + "integrity": "sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==", + "license": "MIT", + "dependencies": { + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", + "license": "BSD-3-Clause" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", + "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", + "license": "MIT", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "license": "MIT", + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/inline-style-prefixer": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.4.tgz", + "integrity": "sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg==", + "license": "MIT", + "dependencies": { + "css-in-js-utils": "^3.1.0", + "fast-loops": "^1.1.3" + } + }, + "node_modules/internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "license": "MIT", + "dependencies": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "license": "MIT" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-invalid-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-invalid-path/-/is-invalid-path-0.1.0.tgz", + "integrity": "sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==", + "license": "MIT", + "dependencies": { + "is-glob": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-invalid-path/node_modules/is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-invalid-path/node_modules/is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-valid-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz", + "integrity": "sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==", + "license": "MIT", + "dependencies": { + "is-invalid-path": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/jest-environment-node/node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/jest-message-util/node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock/node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/jest-mock/node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/jest-util/node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/jest-validate/node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jimp-compact": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz", + "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==", + "license": "MIT" + }, + "node_modules/joi": { + "version": "17.13.4", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.4.tgz", + "integrity": "sha512-1RuuER6kmt8K8I3nIWvPZKi5RQCb568ZPyY4Pwjlua+yo+63ZTmIwxLZH0heBmiKN4uxjvCiarDrjaeH84xicQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/join-component": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/join-component/-/join-component-1.1.0.tgz", + "integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==", + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz", + "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsc-android": { + "version": "250231.0.0", + "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", + "integrity": "sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==", + "license": "BSD-2-Clause" + }, + "node_modules/jsc-safe-url": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", + "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", + "license": "0BSD" + }, + "node_modules/jscodeshift": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", + "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/register": "^7.13.16", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.21.0", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "license": "MIT" + }, + "node_modules/json-schema-deref-sync": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/json-schema-deref-sync/-/json-schema-deref-sync-0.13.0.tgz", + "integrity": "sha512-YBOEogm5w9Op337yb6pAT6ZXDqlxAsQCanM3grid8lMWNxRJO/zWEJi3ZzqDL8boWfwhTFym5EFrNgWwpqcBRg==", + "license": "MIT", + "dependencies": { + "clone": "^2.1.2", + "dag-map": "~1.0.0", + "is-valid-path": "^0.1.1", + "lodash": "^4.17.13", + "md5": "~2.2.0", + "memory-cache": "~0.2.0", + "traverse": "~0.6.6", + "valid-url": "~1.0.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/json-schema-deref-sync/node_modules/md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha512-PlGG4z5mBANDGCKsYQe0CaUYHdZYZt8ZPZLmEt+Urf0W4GlpTX4HescwHU+dc9+Z/G/vZKYZYFrwgm9VxK6QOQ==", + "license": "BSD-3-Clause", + "dependencies": { + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lighthouse-logger": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", + "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/lighthouse-logger/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/lighthouse-logger/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/lightningcss": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.19.0.tgz", + "integrity": "sha512-yV5UR7og+Og7lQC+70DA7a8ta1uiOPnWPJfxa0wnxylev5qfo4P+4iMpzWAdYWOca4jdNQZii+bDL/l+4hUXIA==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^1.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.19.0", + "lightningcss-darwin-x64": "1.19.0", + "lightningcss-linux-arm-gnueabihf": "1.19.0", + "lightningcss-linux-arm64-gnu": "1.19.0", + "lightningcss-linux-arm64-musl": "1.19.0", + "lightningcss-linux-x64-gnu": "1.19.0", + "lightningcss-linux-x64-musl": "1.19.0", + "lightningcss-win32-x64-msvc": "1.19.0" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.19.0.tgz", + "integrity": "sha512-wIJmFtYX0rXHsXHSr4+sC5clwblEMji7HHQ4Ub1/CznVRxtCFha6JIt5JZaNf8vQrfdZnBxLLC6R8pC818jXqg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.19.0.tgz", + "integrity": "sha512-Lif1wD6P4poaw9c/4Uh2z+gmrWhw/HtXFoeZ3bEsv6Ia4tt8rOJBdkfVaUJ6VXmpKHALve+iTyP2+50xY1wKPw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.19.0.tgz", + "integrity": "sha512-P15VXY5682mTXaiDtbnLYQflc8BYb774j2R84FgDLJTN6Qp0ZjWEFyN1SPqyfTj2B2TFjRHRUvQSSZ7qN4Weig==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.19.0.tgz", + "integrity": "sha512-zwXRjWqpev8wqO0sv0M1aM1PpjHz6RVIsBcxKszIG83Befuh4yNysjgHVplF9RTU7eozGe3Ts7r6we1+Qkqsww==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.19.0.tgz", + "integrity": "sha512-vSCKO7SDnZaFN9zEloKSZM5/kC5gbzUjoJQ43BvUpyTFUX7ACs/mDfl2Eq6fdz2+uWhUh7vf92c4EaaP4udEtA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.19.0.tgz", + "integrity": "sha512-0AFQKvVzXf9byrXUq9z0anMGLdZJS+XSDqidyijI5njIwj6MdbvX2UZK/c4FfNmeRa2N/8ngTffoIuOUit5eIQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.19.0.tgz", + "integrity": "sha512-SJoM8CLPt6ECCgSuWe+g0qo8dqQYVcPiW2s19dxkmSI5+Uu1GIRzyKA0b7QqmEXolA+oSJhQqCmJpzjY4CuZAg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.19.0.tgz", + "integrity": "sha512-C+VuUTeSUOAaBZZOPT7Etn/agx/MatzJzGRkeV+zEABmPuntv1zihncsi+AyGmjkkzq3wVedEy7h0/4S84mUtg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "license": "MIT", + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/log-symbols/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/logkitty": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz", + "integrity": "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==", + "license": "MIT", + "dependencies": { + "ansi-fragments": "^0.2.1", + "dayjs": "^1.8.15", + "yargs": "^15.1.0" + }, + "bin": { + "logkitty": "bin/logkitty.js" + } + }, + "node_modules/logkitty/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/logkitty/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/logkitty/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/logkitty/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/logkitty/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marky": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz", + "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==", + "license": "Apache-2.0" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "license": "BSD-3-Clause", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/md5-file": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-3.2.3.tgz", + "integrity": "sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw==", + "license": "MIT", + "dependencies": { + "buffer-alloc": "^1.1.0" + }, + "bin": { + "md5-file": "cli.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/md5hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/md5hex/-/md5hex-1.0.0.tgz", + "integrity": "sha512-c2YOUbp33+6thdCUi34xIyOU/a7bvGKj/3DB1iaPMTuPHf/Q2d5s4sn1FaCOO43XkXggnb08y5W2PU8UNYNLKQ==", + "license": "MIT" + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "license": "MIT" + }, + "node_modules/memory-cache": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", + "integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==", + "license": "BSD-2-Clause" + }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "license": "MIT", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/metro": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.12.tgz", + "integrity": "sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "accepts": "^1.3.7", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "denodeify": "^1.2.1", + "error-stack-parser": "^2.0.6", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.23.1", + "image-size": "^1.0.2", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.80.12", + "metro-cache": "0.80.12", + "metro-cache-key": "0.80.12", + "metro-config": "0.80.12", + "metro-core": "0.80.12", + "metro-file-map": "0.80.12", + "metro-resolver": "0.80.12", + "metro-runtime": "0.80.12", + "metro-source-map": "0.80.12", + "metro-symbolicate": "0.80.12", + "metro-transform-plugins": "0.80.12", + "metro-transform-worker": "0.80.12", + "mime-types": "^2.1.27", + "nullthrows": "^1.1.1", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "strip-ansi": "^6.0.0", + "throat": "^5.0.0", + "ws": "^7.5.10", + "yargs": "^17.6.2" + }, + "bin": { + "metro": "src/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.12.tgz", + "integrity": "sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "hermes-parser": "0.23.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer/node_modules/hermes-estree": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", + "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", + "license": "MIT" + }, + "node_modules/metro-babel-transformer/node_modules/hermes-parser": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", + "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.23.1" + } + }, + "node_modules/metro-cache": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.12.tgz", + "integrity": "sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA==", + "license": "MIT", + "dependencies": { + "exponential-backoff": "^3.1.1", + "flow-enums-runtime": "^0.0.6", + "metro-core": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-cache-key": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.12.tgz", + "integrity": "sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-config": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.12.tgz", + "integrity": "sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ==", + "license": "MIT", + "dependencies": { + "connect": "^3.6.5", + "cosmiconfig": "^5.0.5", + "flow-enums-runtime": "^0.0.6", + "jest-validate": "^29.6.3", + "metro": "0.80.12", + "metro-cache": "0.80.12", + "metro-core": "0.80.12", + "metro-runtime": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-core": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.12.tgz", + "integrity": "sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-file-map": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.12.tgz", + "integrity": "sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.0.3", + "debug": "^2.2.0", + "fb-watchman": "^2.0.0", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "micromatch": "^4.0.4", + "node-abort-controller": "^3.1.1", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/metro-file-map/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/metro-file-map/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/metro-minify-terser": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.12.tgz", + "integrity": "sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "terser": "^5.15.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-resolver": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.12.tgz", + "integrity": "sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-runtime": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.12.tgz", + "integrity": "sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-source-map": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.12.tgz", + "integrity": "sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-symbolicate": "0.80.12", + "nullthrows": "^1.1.1", + "ob1": "0.80.12", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-symbolicate": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.12.tgz", + "integrity": "sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-source-map": "0.80.12", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "through2": "^2.0.1", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-symbolicate/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-transform-plugins": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.12.tgz", + "integrity": "sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-transform-worker": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.12.tgz", + "integrity": "sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/types": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "metro": "0.80.12", + "metro-babel-transformer": "0.80.12", + "metro-cache": "0.80.12", + "metro-cache-key": "0.80.12", + "metro-minify-terser": "0.80.12", + "metro-source-map": "0.80.12", + "metro-transform-plugins": "0.80.12", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/metro/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "license": "MIT" + }, + "node_modules/metro/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/metro/node_modules/hermes-estree": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", + "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", + "license": "MIT" + }, + "node_modules/metro/node_modules/hermes-parser": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", + "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.23.1" + } + }, + "node_modules/metro/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/metro/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/metro/node_modules/ws": { + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", + "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", + "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/nested-error-stacks": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz", + "integrity": "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==", + "license": "MIT" + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "license": "MIT" + }, + "node_modules/nocache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", + "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "license": "MIT" + }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.51", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz", + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/node-stream-zip": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", + "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/antelle" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-package-arg": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-7.0.0.tgz", + "integrity": "sha512-xXxr8y5U0kl8dVkz2oK7yZjPBvqM2fwaO5l3Yg13p03v8+E3qQcD0JNhHzjL1vyGgxcKkD0cco+NLR72iuPk3g==", + "license": "ISC", + "dependencies": { + "hosted-git-info": "^3.0.2", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "node_modules/npm-package-arg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "license": "MIT", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "license": "MIT" + }, + "node_modules/ob1": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.12.tgz", + "integrity": "sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", + "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", + "license": "MIT", + "dependencies": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/ora/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ora/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parse-png": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz", + "integrity": "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==", + "license": "MIT", + "dependencies": { + "pngjs": "^3.3.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.2.tgz", + "integrity": "sha512-cfDHL6LStTEKlNilboNtobT/kEa30PtAf2Q1OgszfrG/rpVl1xaFWT9ktfkS306GmHgmnad1Sw4wabhlvFtsTw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/plist/node_modules/@xmldom/xmldom": { + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", + "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/plist/node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pretty-format/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/pretty-format/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "license": "MIT", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qrcode-terminal": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz", + "integrity": "sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==", + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/querystring": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "license": "MIT", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-devtools-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.3.2.tgz", + "integrity": "sha512-crr9HkVrDiJ0A4zot89oS0Cgv0Oa4OG1Em4jit3P3ZxZSKPMYyMjfwMqgcJna9o625g8oN87rBm8SWWrSTBZxg==", + "license": "MIT", + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-devtools-core/node_modules/ws": { + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", + "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" + }, + "node_modules/react-freeze": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.4.tgz", + "integrity": "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=17.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-native": { + "version": "0.74.5", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.74.5.tgz", + "integrity": "sha512-Bgg2WvxaGODukJMTZFTZBNMKVaROHLwSb8VAGEdrlvKwfb1hHg/3aXTUICYk7dwgAnb+INbGMwnF8yeAgIUmqw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@jest/create-cache-key-function": "^29.6.3", + "@react-native-community/cli": "13.6.9", + "@react-native-community/cli-platform-android": "13.6.9", + "@react-native-community/cli-platform-ios": "13.6.9", + "@react-native/assets-registry": "0.74.87", + "@react-native/codegen": "0.74.87", + "@react-native/community-cli-plugin": "0.74.87", + "@react-native/gradle-plugin": "0.74.87", + "@react-native/js-polyfills": "0.74.87", + "@react-native/normalize-colors": "0.74.87", + "@react-native/virtualized-lists": "0.74.87", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "base64-js": "^1.5.1", + "chalk": "^4.0.0", + "event-target-shim": "^5.0.1", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "jest-environment-node": "^29.6.3", + "jsc-android": "^250231.0.0", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.80.3", + "metro-source-map": "^0.80.3", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "pretty-format": "^26.5.2", + "promise": "^8.3.0", + "react-devtools-core": "^5.0.0", + "react-refresh": "^0.14.0", + "react-shallow-renderer": "^16.15.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.24.0-canary-efb381bbf-20230505", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.2", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.2.6", + "react": "18.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-native-gesture-handler": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.16.2.tgz", + "integrity": "sha512-vGFlrDKlmyI+BT+FemqVxmvO7nqxU33cgXVsn6IKAFishvlG3oV2Ds67D5nPkHMea8T+s1IcuMm0bF8ntZtAyg==", + "license": "MIT", + "dependencies": { + "@egjs/hammerjs": "^2.0.17", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "lodash": "^4.17.21", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-helmet-async": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-native-helmet-async/-/react-native-helmet-async-2.0.4.tgz", + "integrity": "sha512-m3CkXWss6B1dd6mCMleLpzDCJJGGaHOLQsUzZv8kAASJmMfmVT4d2fx375iXKTRWT25ThBfae3dECuX5cq/8hg==", + "license": "Apache-2.0", + "dependencies": { + "invariant": "^2.2.4", + "react-fast-compare": "^3.2.2", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-native-safe-area-context": { + "version": "4.10.5", + "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.10.5.tgz", + "integrity": "sha512-Wyb0Nqw2XJ6oZxW/cK8k5q7/UAhg/wbEG6UVf89rQqecDZTDA5ic//P9J6VvJRVZerzGmxWQpVuM7f+PRYUM4g==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-screens": { + "version": "3.31.1", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.31.1.tgz", + "integrity": "sha512-8fRW362pfZ9y4rS8KY5P3DFScrmwo/vu1RrRMMx0PNHbeC9TLq0Kw1ubD83591yz64gLNHFLTVkTJmWeWCXKtQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "react-freeze": "^1.0.0", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-svg": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.2.0.tgz", + "integrity": "sha512-R0E6IhcJfVLsL0lRmnUSm72QO+mTqcAOM5Jb8FVGxJqX3NfJMlMP0YyvcajZiaRR8CqQUpEoqrY25eyZb006kw==", + "license": "MIT", + "dependencies": { + "css-select": "^5.1.0", + "css-tree": "^1.1.3" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-web": { + "version": "0.19.13", + "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.13.tgz", + "integrity": "sha512-etv3bN8rJglrRCp/uL4p7l8QvUNUC++QwDbdZ8CB7BvZiMvsxfFIRM1j04vxNldG3uo2puRd6OSWR3ibtmc29A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.6", + "@react-native/normalize-colors": "^0.74.1", + "fbjs": "^3.0.4", + "inline-style-prefixer": "^6.0.1", + "memoize-one": "^6.0.0", + "nullthrows": "^1.1.1", + "postcss-value-parser": "^4.2.0", + "styleq": "^0.1.3" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/react-native-web/node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/react-native/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/react-native/node_modules/@react-native/normalize-colors": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.74.87.tgz", + "integrity": "sha512-Xh7Nyk/MPefkb0Itl5Z+3oOobeG9lfLb7ZOY2DKpFnoCE1TzBmib9vMNdFaLdSxLIP+Ec6icgKtdzYg8QUPYzA==", + "license": "MIT" + }, + "node_modules/react-native/node_modules/@react-native/virtualized-lists": { + "version": "0.74.87", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.74.87.tgz", + "integrity": "sha512-lsGxoFMb0lyK/MiplNKJpD+A1EoEUumkLrCjH4Ht+ZlG8S0BfCxmskLZ6qXn3BiDSkLjfjI/qyZ3pnxNBvkXpQ==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.2.6", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-native/node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/react-native/node_modules/@types/yargs": { + "version": "15.0.20", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.20.tgz", + "integrity": "sha512-KIkX+/GgfFitlASYCGoSF+T4XRXhOubJLhkLVtSfsRTe9jWMmuM2g28zQ41BtPTG7TRBb2xHW+LCNVE9QR/vsg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-native/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/react-native/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "license": "MIT", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/react-native/node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "license": "MIT", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/react-native/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/react-native/node_modules/scheduler": { + "version": "0.24.0-canary-efb381bbf-20230505", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", + "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/react-native/node_modules/ws": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.4.tgz", + "integrity": "sha512-PNIUUyLI5YpkJZj60YBzX1o0ByQ4ovvfmq9N/Kig/PAYbVlGyz4R6G0SEWrD0O9acc0sT2+IdMBVLFv8FSi0Nw==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", + "license": "BSD" + }, + "node_modules/recast": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", + "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", + "license": "MIT", + "dependencies": { + "ast-types": "0.15.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.2.tgz", + "integrity": "sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/remove-trailing-slash": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz", + "integrity": "sha512-o4S4Qh6L2jpnCy83ysZDau+VORNvnFw07CKSAymkd6ICNVEPisMyzlc00KlvvicsxKck94SEwhDnMNdICzO+tA==", + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/requireg": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/requireg/-/requireg-0.2.2.tgz", + "integrity": "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==", + "dependencies": { + "nested-error-stacks": "~2.0.1", + "rc": "~1.2.7", + "resolve": "~1.7.1" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/requireg/node_modules/resolve": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "license": "MIT", + "dependencies": { + "path-parse": "^1.0.5" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-workspace-root": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.1.tgz", + "integrity": "sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==", + "license": "MIT" + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "license": "MIT", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-static/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/serve-static/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static/node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", + "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "license": "MIT", + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, + "node_modules/simple-plist/node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/simple-plist/node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/slugify": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz", + "integrity": "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/ssri": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/stacktrace-parser": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", + "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/stream-slice": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz", + "integrity": "sha512-QzQxpoacatkreL6jsxnVb7X5R/pGw9OUv2qWTYWnmLpg4NdN31snPy/f3TdQE1ZUXaThRvj1Zw4/OGg0ZkaLMA==", + "license": "MIT" + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/structured-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz", + "integrity": "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==", + "license": "MIT" + }, + "node_modules/styleq": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/styleq/-/styleq-0.1.3.tgz", + "integrity": "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA==", + "license": "MIT" + }, + "node_modules/sucrase": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", + "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sudo-prompt": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", + "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "license": "MIT", + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tempy": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.7.1.tgz", + "integrity": "sha512-vXPxwOyaNVi9nyczO16mxmHGpl6ASC5/TVhRRHpqeYHvKQm58EaWNvZXxAhR0lYYnBOQFjXjhzeLsaXdjxLjRg==", + "license": "MIT", + "dependencies": { + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.49.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.49.0.tgz", + "integrity": "sha512-SNiDnXyHSrxVcIOtVbULzcTmniUiwcV7Nwdyj1twVubeTmbjoa8p69KKDpfkdoOavuM4/GRm1+ykI8qqnavHoA==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/traverse": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.11.tgz", + "integrity": "sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==", + "license": "MIT", + "dependencies": { + "gopd": "^1.2.0", + "typedarray.prototype.slice": "^1.0.5", + "which-typed-array": "^1.1.18" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/turbo-stream": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.1.tgz", + "integrity": "sha512-v8kOJXpG3WoTN/+at8vK7erSzo6nW6CIaeOvNOkHQVDajfz1ZVeSxCbc6tOH4hrGZW7VUCV0TOXd8CPzYnYkrw==", + "license": "ISC" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray.prototype.slice": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.5.tgz", + "integrity": "sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "math-intrinsics": "^1.1.0", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-offset": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "devOptional": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ua-parser-js": { + "version": "1.0.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", + "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "MIT", + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz", + "integrity": "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "license": "ISC", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/url-join": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", + "integrity": "sha512-EGXjXJZhIHiQMK2pQukuFcL303nskqIRzWvPvV5O8miOfwoUb9G+a/Cld60kUyeaybEI94wvVClT10DtfeAExA==", + "license": "MIT" + }, + "node_modules/use-latest-callback": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.6.tgz", + "integrity": "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/valid-url": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==" + }, + "node_modules/validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", + "license": "ISC", + "dependencies": { + "builtins": "^1.0.3" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", + "license": "MIT" + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/warn-once": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", + "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==", + "license": "MIT" + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "license": "MIT", + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/whatwg-url-without-unicode": { + "version": "8.0.0-3", + "resolved": "https://registry.npmjs.org/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz", + "integrity": "sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==", + "license": "MIT", + "dependencies": { + "buffer": "^5.4.3", + "punycode": "^2.1.1", + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/whatwg-url-without-unicode/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wonka": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/wonka/-/wonka-4.0.15.tgz", + "integrity": "sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "license": "Apache-2.0", + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xcode/node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/xml2js": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz", + "integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-14.0.0.tgz", + "integrity": "sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-2.1.0.tgz", + "integrity": "sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.18.0" + } + } + } +} diff --git a/src/backend/build.gradle b/src/backend/build.gradle index dc881b7..bc0fa6c 100644 --- a/src/backend/build.gradle +++ b/src/backend/build.gradle @@ -43,6 +43,9 @@ dependencies { // --- Redis 작업 큐 (RenderJob·서류 생성·알림 발행) --- implementation 'org.springframework.boot:spring-boot-starter-data-redis' + // --- 메일 발송(자체 Postfix SMTP — 옥션 개설 통지·EDM·비밀번호 재설정) --- + implementation 'org.springframework.boot:spring-boot-starter-mail' + // --- JWT (행사 단위 RBAC 인증) --- implementation "io.jsonwebtoken:jjwt-api:${jjwtVersion}" runtimeOnly "io.jsonwebtoken:jjwt-impl:${jjwtVersion}" diff --git a/src/backend/src/main/java/com/zioinfo/kintex/auction/AuctionMapper.java b/src/backend/src/main/java/com/zioinfo/kintex/auction/AuctionMapper.java index 91b5e82..364ae85 100644 --- a/src/backend/src/main/java/com/zioinfo/kintex/auction/AuctionMapper.java +++ b/src/backend/src/main/java/com/zioinfo/kintex/auction/AuctionMapper.java @@ -231,6 +231,38 @@ public interface AuctionMapper { """) List> listMyAwardedBooths(@Param("companyId") String companyId); + // ── 옥션 개설 통지 대상(§5B 인앱 + 이메일) ────────────────────────────────── + /** 행사명(통지 본문용). */ + @Select("SELECT name FROM event WHERE id = #{eventId}") + String findEventName(@Param("eventId") String eventId); + + /** + * 초대 옥션의 초대 업체 소속 CONTRACTOR 사용자(통지 대상). email 은 발송 경로 한정 원문. + * ★ 별칭 쌍따옴표 필수(카멜케이스 키 보존). + */ + @Select(""" + SELECT DISTINCT u.id AS "userId", u.email AS "email", u.display_name AS "displayName" + FROM auction_invite ai + JOIN event_member em ON em.company_id = ai.company_id + AND em.event_id = (SELECT event_id FROM auction WHERE id = #{auctionId}) + JOIN app_user u ON u.id = em.user_id + WHERE ai.auction_id = #{auctionId} + AND em.role_code = 'CONTRACTOR' + AND u.status = 'ACTIVE' + """) + List> listInvitedContractorUsers(@Param("auctionId") String auctionId); + + /** 공개 옥션(초대 0) — 행사 전체 CONTRACTOR 사용자(통지 대상). */ + @Select(""" + SELECT DISTINCT u.id AS "userId", u.email AS "email", u.display_name AS "displayName" + FROM event_member em + JOIN app_user u ON u.id = em.user_id + WHERE em.event_id = #{eventId} + AND em.role_code = 'CONTRACTOR' + AND u.status = 'ACTIVE' + """) + List> listEventContractorUsers(@Param("eventId") String eventId); + // ── F035 BOQ 물량 집계(M2 booth/layout·M4 utility_order — 읽기 전용) ────────── /** * 부스 폴리곤 면적·둘레·부스수·최대높이 집계. boothNo 가 null 이면 행사 전체 부스, 있으면 해당 부스코드만. diff --git a/src/backend/src/main/java/com/zioinfo/kintex/auction/AuctionService.java b/src/backend/src/main/java/com/zioinfo/kintex/auction/AuctionService.java index 2b65143..e35c424 100644 --- a/src/backend/src/main/java/com/zioinfo/kintex/auction/AuctionService.java +++ b/src/backend/src/main/java/com/zioinfo/kintex/auction/AuctionService.java @@ -30,13 +30,24 @@ public class AuctionService { private static final int MAX_LIMIT = 500; + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AuctionService.class); + private final AuctionMapper mapper; private final com.zioinfo.kintex.settlement.SettlementService settlementService; + private final com.zioinfo.kintex.work.notification.NotificationService notificationService; + private final com.zioinfo.kintex.mail.MailService mailService; + private final com.zioinfo.kintex.mail.MailProperties mailProperties; public AuctionService(AuctionMapper mapper, - com.zioinfo.kintex.settlement.SettlementService settlementService) { + com.zioinfo.kintex.settlement.SettlementService settlementService, + com.zioinfo.kintex.work.notification.NotificationService notificationService, + com.zioinfo.kintex.mail.MailService mailService, + com.zioinfo.kintex.mail.MailProperties mailProperties) { this.mapper = mapper; this.settlementService = settlementService; + this.notificationService = notificationService; + this.mailService = mailService; + this.mailProperties = mailProperties; } // ── 목록(SCR-26) ────────────────────────────────────────────────────────── @@ -376,9 +387,73 @@ public class AuctionService { mapper.insertInvite(inv); } } + + // 개설 통지 — 대상 공사업체(초대 있으면 초대 업체, 없으면 행사 CONTRACTOR 전체)에게 + // ①§5B 인앱 알림 ②이메일(MAIL_ENABLED=false면 인앱만). 통지 실패는 개설을 되돌리지 않는다. + notifyAuctionOpened(id, req.eventId(), req.title(), req.deadline()); + return toSummary(mapper.findAuction(id)); } + /** 개설 통지 발행(인앱 + 이메일). 실패 격리 — 알림 오류가 개설 트랜잭션을 깨지 않는다. */ + private void notifyAuctionOpened(String auctionId, String eventId, String title, String deadline) { + try { + List> targets = mapper.countInvites(auctionId) > 0 + ? mapper.listInvitedContractorUsers(auctionId) + : mapper.listEventContractorUsers(eventId); + if (targets == null || targets.isEmpty()) { + return; + } + String eventName = mapper.findEventName(eventId); + if (eventName == null || eventName.isBlank()) { + eventName = "행사"; + } + String link = "/auctions/" + auctionId; + String inAppMsg = "응찰 마감 " + shortDeadline(deadline) + " · " + eventName; + String mailLink = mailProperties.getWebBaseUrl() + link; + String subject = "[KINTEX] 공사 옥션 개설 안내 · " + title; + String html = com.zioinfo.kintex.mail.MailTemplates.auctionOpened( + eventName, title, shortDeadline(deadline), mailLink); + + for (Map u : targets) { + String userId = str(u.get("userId")); + if (userId == null) { + continue; + } + // ① 인앱 알림(발송 채널 단일화 §7-6) + try { + notificationService.notify(userId, eventId, "MESSAGE", + "새 공사 옥션 개설: " + title, inAppMsg, link); + } catch (RuntimeException e) { + log.warn("옥션 인앱 통지 실패(무시): auction={} reason={}", auctionId, e.getClass().getSimpleName()); + } + // ② 이메일(@Async·실패 격리 — MAIL_ENABLED=false면 내부에서 스킵) + String email = str(u.get("email")); + if (email != null && !email.isBlank()) { + mailService.send("AUCTION_OPEN", auctionId, email, subject, html); + } + } + } catch (RuntimeException e) { + log.warn("옥션 개설 통지 처리 실패(개설은 정상): auction={} reason={}", + auctionId, e.getClass().getSimpleName()); + } + } + + /** deadline(ISO 또는 원문)에서 날짜/시각 앞부분만 짧게 — 통지 표기용(파싱 실패 시 원문). */ + private static String shortDeadline(String deadline) { + if (deadline == null || deadline.isBlank()) { + return "-"; + } + String s = deadline.trim(); + int t = s.indexOf('T'); + if (t > 0) { + String date = s.substring(0, t); + String time = s.length() >= t + 6 ? s.substring(t + 1, t + 6) : ""; + return time.isEmpty() ? date : date + " " + time; + } + return s.length() > 16 ? s.substring(0, 16) : s; + } + // ── 업체 포털 대시보드(SCR-38) ───────────────────────────────────────────── public ContractorDashboard contractorDashboard(KintexPrincipal principal) { Map co = mapper.findUserCompany(principal.userId()); diff --git a/src/backend/src/main/java/com/zioinfo/kintex/auth/PublicAuthService.java b/src/backend/src/main/java/com/zioinfo/kintex/auth/PublicAuthService.java index 051bddf..2c3c00b 100644 --- a/src/backend/src/main/java/com/zioinfo/kintex/auth/PublicAuthService.java +++ b/src/backend/src/main/java/com/zioinfo/kintex/auth/PublicAuthService.java @@ -41,10 +41,16 @@ public class PublicAuthService { private final PublicAuthMapper mapper; private final PasswordEncoder passwordEncoder; + private final com.zioinfo.kintex.mail.MailService mailService; + private final com.zioinfo.kintex.mail.MailProperties mailProperties; - public PublicAuthService(PublicAuthMapper mapper, PasswordEncoder passwordEncoder) { + public PublicAuthService(PublicAuthMapper mapper, PasswordEncoder passwordEncoder, + com.zioinfo.kintex.mail.MailService mailService, + com.zioinfo.kintex.mail.MailProperties mailProperties) { this.mapper = mapper; this.passwordEncoder = passwordEncoder; + this.mailService = mailService; + this.mailProperties = mailProperties; } /** 회원가입 — 이메일 중복 시 409, 성공 시 민감정보 제외 요약 반환. */ @@ -95,9 +101,14 @@ public class PublicAuthService { String codeHash = passwordEncoder.encode(code); mapper.insertResetCode(email, codeHash, OffsetDateTime.now().plusMinutes(RESET_TTL_MINUTES)); - // 이메일 발송 인프라 부재 → dev 로깅. 코드 값은 마스킹(원문·해시 노출 금지, 계약 §0-3). + // 코드 값은 마스킹 로그(원문·해시 노출 금지, 계약 §0-3). log.info("비밀번호 재설정 코드 발급(email={}, code={}, ttl={}m)", maskEmail(email), maskCode(code), RESET_TTL_MINUTES); + // 재설정 코드 이메일 발송(@Async·실패 격리 — MAIL_ENABLED=false면 스킵 로그). 프론트 흐름은 이메일+코드 입력. + // 링크는 안내용(프론트 reset 화면은 코드 6자리 입력을 사용). + String link = mailProperties.getWebBaseUrl() + "/login?reset=1"; + String html = com.zioinfo.kintex.mail.MailTemplates.passwordReset(code, link, RESET_TTL_MINUTES); + mailService.send("PASSWORD_RESET", null, email, "[KINTEX] 비밀번호 재설정 인증코드", html); } // 존재 여부와 무관하게 동일 응답(사용자 열거 방지). return new MessageResponse(GENERIC_FORGOT_MESSAGE); diff --git a/src/backend/src/main/java/com/zioinfo/kintex/common/error/GlobalExceptionHandler.java b/src/backend/src/main/java/com/zioinfo/kintex/common/error/GlobalExceptionHandler.java index a2a4e21..54efba4 100644 --- a/src/backend/src/main/java/com/zioinfo/kintex/common/error/GlobalExceptionHandler.java +++ b/src/backend/src/main/java/com/zioinfo/kintex/common/error/GlobalExceptionHandler.java @@ -2,6 +2,8 @@ package com.zioinfo.kintex.common.error; import com.zioinfo.kintex.common.ApiResponse; import com.zioinfo.kintex.common.ApiResponse.ApiError; +import com.zioinfo.kintex.system.errorlog.ErrorLogService; +import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; @@ -12,12 +14,19 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; /** * 전역 예외 처리 — 응답에는 코드+요약 메시지만 노출한다. * 스택트레이스·내부 세부는 서버 로그에만 남기고 클라이언트에는 절대 반환하지 않는다(보안 불변). + * 예상치 못한 500 은 관리 조회용으로 요약 1줄만 error_log 에 best-effort 적재한다(스택 미저장). */ @RestControllerAdvice public class GlobalExceptionHandler { private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + private final ErrorLogService errorLog; + + public GlobalExceptionHandler(ErrorLogService errorLog) { + this.errorLog = errorLog; + } + @ExceptionHandler(ApiException.class) public ResponseEntity> handleApi(ApiException ex) { ErrorCode code = ex.getCode(); @@ -39,9 +48,15 @@ public class GlobalExceptionHandler { /** 최종 방어선 — 예상치 못한 예외는 요약 메시지만, 상세는 로그로. */ @ExceptionHandler(Exception.class) - public ResponseEntity> handleUnexpected(Exception ex) { + public ResponseEntity> handleUnexpected(Exception ex, HttpServletRequest req) { log.error("Unhandled exception", ex); ErrorCode code = ErrorCode.INTERNAL; + // 요약 1줄만(예외 클래스 + 메시지 절단). 스택트레이스·민감정보는 저장하지 않는다. + String summary = ex.getClass().getSimpleName() + + (ex.getMessage() == null ? "" : ": " + ex.getMessage()); + errorLog.record(code.name(), summary, + req == null ? null : req.getRequestURI(), + req == null ? null : req.getMethod(), null); return ResponseEntity.status(code.status()) .body(ApiResponse.fail(new ApiError(code.name(), code.defaultMessage()))); } diff --git a/src/backend/src/main/java/com/zioinfo/kintex/common/text/Masking.java b/src/backend/src/main/java/com/zioinfo/kintex/common/text/Masking.java new file mode 100644 index 0000000..4a78bed --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/common/text/Masking.java @@ -0,0 +1,56 @@ +package com.zioinfo.kintex.common.text; + +/** + * PII 마스킹 유틸(§0-3) — 전화/이메일/IP 원문을 응답·로그·저장 전에 마스킹한다. + * 시스템관리 조회(회사 연락처·로그인 이력)에서 공용으로 사용한다. + */ +public final class Masking { + + private Masking() { + } + + /** 010-1234-5678 → 010-****-5678. 형식이 다르면 뒤 4자리만 노출. null 안전. */ + public static String maskPhone(String phone) { + if (phone == null || phone.isBlank()) { + return phone; + } + String digits = phone.replaceAll("[^0-9]", ""); + if (digits.length() < 7) { + return "***"; + } + String last4 = digits.substring(digits.length() - 4); + String head = digits.substring(0, Math.min(3, digits.length() - 4)); + return head + "-****-" + last4; + } + + /** kim.hong@do.com → ki***@do.com. null 안전. */ + public static String maskEmail(String email) { + if (email == null || email.isBlank()) { + return email; + } + int at = email.indexOf('@'); + if (at <= 0) { + return "***"; + } + String local = email.substring(0, at); + String domain = email.substring(at); + String head = local.length() <= 2 ? local.substring(0, 1) : local.substring(0, 2); + return head + "***" + domain; + } + + /** 203.0.113.24 → 203.0.113.* (IPv6 등은 앞 절반만). null 안전. */ + public static String maskIp(String ip) { + if (ip == null || ip.isBlank()) { + return ip; + } + int dot = ip.lastIndexOf('.'); + if (dot > 0) { + return ip.substring(0, dot) + ".*"; + } + int colon = ip.indexOf(':'); + if (colon > 0) { + return ip.substring(0, colon) + ":***"; + } + return "***"; + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/mail/MailBatch.java b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailBatch.java new file mode 100644 index 0000000..44f956d --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailBatch.java @@ -0,0 +1,29 @@ +package com.zioinfo.kintex.mail; + +import java.util.ArrayList; +import java.util.List; + +/** + * 발송 배치 유틸 — 대량 수신자를 고정 크기(예: 50) 청크로 분할한다. 순수 함수(단위 테스트 고정). + */ +public final class MailBatch { + + private MailBatch() { + } + + /** list 를 size 단위 청크로 분할. size <= 0 이면 전체를 단일 청크로 반환. */ + public static List> partition(List list, int size) { + List> out = new ArrayList<>(); + if (list == null || list.isEmpty()) { + return out; + } + if (size <= 0) { + out.add(new ArrayList<>(list)); + return out; + } + for (int i = 0; i < list.size(); i += size) { + out.add(new ArrayList<>(list.subList(i, Math.min(i + size, list.size())))); + } + return out; + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/mail/MailConfig.java b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailConfig.java new file mode 100644 index 0000000..83a1d7d --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailConfig.java @@ -0,0 +1,29 @@ +package com.zioinfo.kintex.mail; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; + +/** + * 메일 발송 비동기 실행기. 대량 EDM 발송이 요청 스레드/공유 풀을 점유하지 않도록 소형 전용 풀을 둔다. + */ +@Configuration +@EnableAsync +public class MailConfig { + + @Bean(name = "mailExecutor") + public Executor mailExecutor() { + ThreadPoolTaskExecutor ex = new ThreadPoolTaskExecutor(); + ex.setCorePoolSize(2); + ex.setMaxPoolSize(4); + ex.setQueueCapacity(1000); // EDM 회당 상한 500 + 여유 + ex.setThreadNamePrefix("mail-"); + ex.setWaitForTasksToCompleteOnShutdown(true); + ex.setAwaitTerminationSeconds(20); + ex.initialize(); + return ex; + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/mail/MailLogMapper.java b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailLogMapper.java new file mode 100644 index 0000000..2ba7ccb --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailLogMapper.java @@ -0,0 +1,25 @@ +package com.zioinfo.kintex.mail; + +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 메일 발송 이력 매퍼(mail_log). 본문·자격증명은 저장하지 않으며 수신자는 마스킹만 기록한다(§0-3). + * tenant_id 는 스키마 DEFAULT 'KINTEX'(V31 표준)에 위임 — 삽입 시 생략한다. + */ +@Mapper +public interface MailLogMapper { + + @Insert(""" + INSERT INTO mail_log (id, category, ref_id, subject, recipient_masked, status, detail) + VALUES (#{id}, #{category}, #{refId}, #{subject}, #{recipientMasked}, #{status}, #{detail}) + """) + int insert(@Param("id") String id, + @Param("category") String category, + @Param("refId") String refId, + @Param("subject") String subject, + @Param("recipientMasked") String recipientMasked, + @Param("status") String status, + @Param("detail") String detail); +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/mail/MailProperties.java b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailProperties.java new file mode 100644 index 0000000..9c97a2e --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailProperties.java @@ -0,0 +1,51 @@ +package com.zioinfo.kintex.mail; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * 메일 발송 채널 설정 — 자체 Postfix SMTP(mail.zioinfo.co.kr, GUARDiA 운영). + * + *

SMTP 자격증명(host/user/password)은 {@code spring.mail.*}(env: SMTP_HOST·SMTP_USER·SMTP_PASSWORD)로만 주입한다. + * 여기서는 발송 on/off({@code enabled})와 발신자 표기({@code from})만 다룬다. 자격증명은 코드·응답·로그에 기재 금지(§0-3). + * + *

    + *
  • {@code MAIL_ENABLED}(기본 false) — 실 발송 스위치. false면 인앱/로깅만 하고 실제 전송은 건너뛴다(정직 로그).
  • + *
  • {@code MAIL_FROM} — From 헤더 표기 주소.
  • + *
+ */ +@ConfigurationProperties(prefix = "kintex.mail") +public class MailProperties { + + /** 실 발송 여부(기본 false — env로 켠다). false면 실제 SMTP 전송 없이 스킵 로그만 남긴다. */ + private boolean enabled = false; + + /** 발신자 주소(From). */ + private String from = "no-reply@kintex.zioinfo.co.kr"; + + /** 프론트 베이스 URL — 메일 내 링크(옥션 상세·재설정 화면) 생성용. */ + private String webBaseUrl = "https://kintex.zioinfo.co.kr"; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getWebBaseUrl() { + return webBaseUrl; + } + + public void setWebBaseUrl(String webBaseUrl) { + this.webBaseUrl = webBaseUrl; + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/mail/MailService.java b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailService.java new file mode 100644 index 0000000..29786f4 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailService.java @@ -0,0 +1,120 @@ +package com.zioinfo.kintex.mail; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.nio.charset.StandardCharsets; +import java.util.UUID; + +/** + * 메일 발송 서비스 — 자체 Postfix SMTP(mail.zioinfo.co.kr) 채널. + * + *

불변 규칙: + *

    + *
  • SMTP 자격증명은 {@code spring.mail.*}(env)로만 로드 — 코드·응답·로그 미기재(§0-3).
  • + *
  • 실패 격리: 발송 실패는 호출 기능(옥션 개설·비번 재설정 등)으로 전파하지 않는다. 1회 재시도 후 이력만 남긴다.
  • + *
  • 수신자는 마스킹(kim***@do.com)만 로그·이력에 기록. 본문은 저장하지 않는다.
  • + *
  • {@code MAIL_ENABLED=false}면 실제 전송 없이 skipped 이력만 남긴다(정직 로그).
  • + *
+ * + *

@Async 로 호출 스레드를 차단하지 않는다(대량 EDM 발송 시 요청 응답 지연 방지). + */ +@Service +public class MailService { + + private static final Logger log = LoggerFactory.getLogger(MailService.class); + + private final MailProperties props; + private final ObjectProvider mailSenderProvider; + private final MailLogMapper mailLogMapper; + + public MailService(MailProperties props, + ObjectProvider mailSenderProvider, + MailLogMapper mailLogMapper) { + this.props = props; + this.mailSenderProvider = mailSenderProvider; + this.mailLogMapper = mailLogMapper; + } + + /** + * 단건 HTML 메일 발송(비동기·실패 격리). category/refId 는 이력 분류용, to 는 발송 경로 한정 원문 수신자. + * MAIL_ENABLED=false 또는 JavaMailSender 미구성 시 실제 전송 없이 skipped 이력만 남긴다. + */ + @Async("mailExecutor") + public void send(String category, String refId, String to, String subject, String htmlBody) { + String masked = maskEmail(to); + if (to == null || to.isBlank()) { + record(category, refId, subject, masked, "skipped", "빈 수신자"); + return; + } + JavaMailSender sender = mailSenderProvider.getIfAvailable(); + if (!props.isEnabled() || sender == null) { + // 실 발송 비활성 — 스킵 이력만(원문·자격증명 미기록). + log.info("메일 발송 스킵(MAIL_ENABLED=false){}: cat={} to={} subj={}", + sender == null ? "/sender-absent" : "", category, masked, subject); + record(category, refId, subject, masked, "skipped", "MAIL_ENABLED=false"); + return; + } + // 실 발송 — 1회 재시도. 최종 실패도 예외 전파 없이 이력만. + RuntimeException last = null; + for (int attempt = 1; attempt <= 2; attempt++) { + try { + var message = sender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, false, StandardCharsets.UTF_8.name()); + helper.setFrom(props.getFrom()); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlBody, true); + sender.send(message); + record(category, refId, subject, masked, "sent", null); + return; + } catch (Exception e) { + last = e instanceof RuntimeException re ? re : new RuntimeException(e.getClass().getSimpleName()); + log.warn("메일 발송 실패(시도 {}/2): cat={} to={} reason={}", + attempt, category, masked, e.getClass().getSimpleName()); + } + } + record(category, refId, subject, masked, "failed", + last == null ? "unknown" : last.getClass().getSimpleName()); + } + + /** 이력 기록(실패해도 호출 기능에 전파하지 않는다). */ + private void record(String category, String refId, String subject, String masked, + String status, String detail) { + try { + mailLogMapper.insert("ml-" + UUID.randomUUID().toString().replace("-", "").substring(0, 20), + category, refId, truncate(subject, 300), masked, status, truncate(detail, 300)); + } catch (RuntimeException e) { + log.warn("메일 이력 기록 실패(무시): cat={} status={} reason={}", category, status, e.getClass().getSimpleName()); + } + } + + /** 이메일 마스킹 — kim***@domain.com. 로그·이력 노출 안전 형식. */ + static String maskEmail(String email) { + if (email == null || email.isBlank()) { + return "***"; + } + int at = email.indexOf('@'); + if (at <= 0) { + return "***"; + } + String local = email.substring(0, at); + String domain = email.substring(at); + if (local.length() <= 3) { + return local.charAt(0) + "***" + domain; + } + return local.substring(0, 3) + "***" + domain; + } + + private static String truncate(String s, int max) { + if (s == null) { + return null; + } + return s.length() <= max ? s : s.substring(0, max); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/mail/MailTemplates.java b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailTemplates.java new file mode 100644 index 0000000..427f3cb --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/mail/MailTemplates.java @@ -0,0 +1,67 @@ +package com.zioinfo.kintex.mail; + +/** + * 짧은 HTML 메일 본문 템플릿. 인라인 스타일 최소·외부 리소스 없음. 본문은 저장하지 않는다(mail_log 는 제목만). + * 정보통신망법: 광고성(EDM)에는 수신거부 안내 문구를 하단에 포함한다. + */ +public final class MailTemplates { + + private MailTemplates() { + } + + private static final String WRAP_HEAD = + "

"; + private static final String WRAP_FOOT = + "
" + + "

KINTEX 전시운영 시스템 · 본 메일은 발신 전용입니다.

"; + + /** 옥션 개설 통지(공사업체 대상) — 행사명·옥션 제목·마감·자료 열람 링크. */ + public static String auctionOpened(String eventName, String auctionTitle, String deadline, String link) { + return WRAP_HEAD + + "

새 공사 옥션이 개설되었습니다

" + + "

행사 " + esc(eventName) + "

" + + "

옥션 " + esc(auctionTitle) + "

" + + "

응찰 마감 " + esc(deadline) + "

" + + "

자료 열람 및 응찰

" + + "

봉인 입찰 — 마감 전 타사 응찰가는 공개되지 않습니다.

" + + WRAP_FOOT; + } + + /** 비밀번호 재설정 — 6자리 인증코드 + 로그인 페이지 링크. */ + public static String passwordReset(String code, String link, int ttlMinutes) { + return WRAP_HEAD + + "

비밀번호 재설정 안내

" + + "

아래 인증코드를 재설정 화면에 입력해 주세요. 유효시간은 " + ttlMinutes + "분입니다.

" + + "

" + + esc(code) + "

" + + "

재설정 화면 열기

" + + "

본인이 요청하지 않았다면 이 메일을 무시하세요.

" + + WRAP_FOOT; + } + + /** EDM 광고 본문 — 캠페인 명 + 안내 + 정보통신망법 수신거부 문구. */ + public static String edm(String campaignName, String eventName) { + return WRAP_HEAD + + "

(광고) " + esc(eventName) + "

" + + "

" + esc(campaignName) + "

" + + "

안녕하세요. KINTEX가 준비한 전시·행사 소식을 전해드립니다. " + + "자세한 내용과 사전등록은 아래에서 확인하실 수 있습니다.

" + + "
" + + "

본 메일은 수신동의(마케팅 정보 수신)를 하신 분께 발송되었습니다. " + + "수신을 원치 않으시면 마이페이지 > 수신설정에서 수신거부하실 수 있습니다. " + + "(정보통신망 이용촉진 및 정보보호 등에 관한 법률 준수)

" + + "

KINTEX 전시운영 시스템 · 발신 전용

"; + } + + /** 최소 HTML 이스케이프(제한 문자만) — 사용자 입력 값이 본문에 삽입될 때 태그 주입 방지. */ + private static String esc(String s) { + if (s == null) { + return ""; + } + return s.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingController.java b/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingController.java index 9860b32..89b65d7 100644 --- a/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingController.java +++ b/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingController.java @@ -46,6 +46,16 @@ public class MarketingController { return ApiResponse.ok(service.createCampaign(eventId, req)); } + /** 캠페인 발송(수신동의자 한정) — 매니저 이상. 정보통신망법 준수·회당 상한·배치 분할은 서비스가 강제. */ + @Audited(action = "CAMPAIGN_SEND", targetType = "edm_campaign") + @PostMapping("/campaigns/{id}/send") + public ApiResponse sendCampaign(@AuthenticationPrincipal KintexPrincipal principal, + @PathVariable String eventId, + @PathVariable String id) { + guard.requireRole(principal, eventId, EventRole.ORGANIZER, EventRole.HALL_MANAGER); + return ApiResponse.ok(service.sendCampaign(eventId, id)); + } + /** 스폰서십 패키지·판매 현황. */ @GetMapping("/sponsorship") public ApiResponse sponsorship(@AuthenticationPrincipal KintexPrincipal principal, diff --git a/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingMapper.java b/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingMapper.java index 361af7d..e166d57 100644 --- a/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingMapper.java +++ b/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingMapper.java @@ -43,6 +43,40 @@ public interface MarketingMapper { @Select("SELECT count(*) FROM event WHERE id = #{eventId}") long eventExists(@Param("eventId") String eventId); + // ── 캠페인 발송(수신동의자 한정) ── + /** 캠페인 단건(발송 게이트용) — 소속 행사·현재 상태. */ + @Select(""" + SELECT id, event_id AS "eventId", name, status + FROM edm_campaign + WHERE id = #{id} AND event_id = #{eventId} + """) + Map findCampaign(@Param("eventId") String eventId, @Param("id") String id); + + /** + * 발송 대상 이메일(수신동의 = agree_marketing=true, 이메일 보유). 원문 이메일은 발송 경로 한정 — + * 응답/로그에 노출하지 않는다. 회당 상한(limit) 가드는 서비스가 적용. + */ + @Select(""" + SELECT DISTINCT lower(email) AS "email" + FROM visitor_registration + WHERE event_id = #{eventId} + AND agree_marketing = true + AND email IS NOT NULL AND email <> '' + ORDER BY lower(email) + LIMIT #{limit} + """) + List> listMarketingRecipients(@Param("eventId") String eventId, @Param("limit") int limit); + + /** 발송 결과 반영 — 상태·발송 건수(audience)·표시 메타 갱신. */ + @org.apache.ibatis.annotations.Update(""" + UPDATE edm_campaign + SET status = #{status}, audience = #{sentCount}, meta = #{meta}, updated_at = now() + WHERE id = #{id} AND event_id = #{eventId} + """) + int markCampaignSent(@Param("eventId") String eventId, @Param("id") String id, + @Param("status") String status, @Param("sentCount") int sentCount, + @Param("meta") String meta); + // ── 스폰서십 ── @Select(""" SELECT id, code, name, name_ko AS "nameKo", price, accent, diff --git a/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingService.java b/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingService.java index 406d84f..63a91b5 100644 --- a/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingService.java +++ b/src/backend/src/main/java/com/zioinfo/kintex/marketing/MarketingService.java @@ -20,10 +20,20 @@ public class MarketingService { private static final ObjectMapper JSON = new ObjectMapper(); - private final MarketingMapper mapper; + /** EDM 회당 발송 상한(가드) 및 배치 크기. */ + private static final int SEND_CAP = 500; + private static final int BATCH_SIZE = 50; - public MarketingService(MarketingMapper mapper) { + private final MarketingMapper mapper; + private final com.zioinfo.kintex.mail.MailService mailService; + private final com.zioinfo.kintex.mail.MailProperties mailProperties; + + public MarketingService(MarketingMapper mapper, + com.zioinfo.kintex.mail.MailService mailService, + com.zioinfo.kintex.mail.MailProperties mailProperties) { this.mapper = mapper; + this.mailService = mailService; + this.mailProperties = mailProperties; } // ── 캠페인 ── @@ -60,6 +70,54 @@ public class MarketingService { return new CampaignDto(id, name, status, audience, meta, "-", "-"); } + /** + * 캠페인 실 발송(수신동의자 한정). 정보통신망법 준수: agree_marketing=true + 이메일 보유자만, + * 회당 상한 {@value #SEND_CAP} 건, {@value #BATCH_SIZE} 건 배치. 상태를 done 으로 전이하고 발송 건수를 기록한다. + * 수신자 원문 이메일은 발송 경로 한정 — 응답/로그에는 건수만 노출한다(§0-3). + */ + public CampaignSendResult sendCampaign(String eventId, String campaignId) { + Map c = mapper.findCampaign(eventId, campaignId); + if (c == null) { + throw new ApiException(ErrorCode.NOT_FOUND, "존재하지 않는 캠페인입니다."); + } + String status = str(c.get("status")); + if ("sending".equalsIgnoreCase(status) || "done".equalsIgnoreCase(status)) { + throw new ApiException(ErrorCode.CONFLICT, "이미 발송되었거나 발송 중인 캠페인입니다."); + } + String name = str(c.get("name")); + String eventName = null; + + List> recipients = mapper.listMarketingRecipients(eventId, SEND_CAP); + List emails = new ArrayList<>(); + if (recipients != null) { + for (Map r : recipients) { + String e = str(r.get("email")); + if (e != null && !e.isBlank()) { + emails.add(e); + } + } + } + + String subject = "[KINTEX] " + (name == null ? "행사 소식" : name); + String html = com.zioinfo.kintex.mail.MailTemplates.edm(name, eventName == null ? "KINTEX" : eventName); + + int sent = 0; + // 50건 배치로 분할 발송(각 건은 MailService @Async·실패 격리). MAIL_ENABLED=false면 내부에서 스킵. + for (List batch : com.zioinfo.kintex.mail.MailBatch.partition(emails, BATCH_SIZE)) { + for (String email : batch) { + mailService.send("EDM", campaignId, email, subject, html); + sent++; + } + } + + boolean mailEnabled = mailProperties.isEnabled(); + String meta = mailEnabled + ? "발송 완료: " + sent + "건 (수신동의자)" + : "발송 대상 " + sent + "건 (MAIL 비활성 — 실 전송 없음)"; + mapper.markCampaignSent(eventId, campaignId, "done", sent, meta); + return new CampaignSendResult(campaignId, "done", sent, mailEnabled, meta); + } + // ── 스폰서십 ── public SponsorshipView sponsorship(String eventId) { List> pkgRows = mapper.findPackages(eventId); diff --git a/src/backend/src/main/java/com/zioinfo/kintex/marketing/dto/MarketingDtos.java b/src/backend/src/main/java/com/zioinfo/kintex/marketing/dto/MarketingDtos.java index 89acc7f..328bd5f 100644 --- a/src/backend/src/main/java/com/zioinfo/kintex/marketing/dto/MarketingDtos.java +++ b/src/backend/src/main/java/com/zioinfo/kintex/marketing/dto/MarketingDtos.java @@ -21,6 +21,11 @@ public final class MarketingDtos { String scheduleType, String scheduledAt) { } + /** 캠페인 발송 결과 — 발송 건수·상태. 수신자 원문/PII 는 포함하지 않는다. */ + public record CampaignSendResult(String id, String status, int sentCount, boolean mailEnabled, + String meta) { + } + // ── SCR-34 스폰서십 ── public record SponsorshipView(List kpis, List tiers, List sponsors) { } diff --git a/src/backend/src/main/java/com/zioinfo/kintex/security/LoginAttemptService.java b/src/backend/src/main/java/com/zioinfo/kintex/security/LoginAttemptService.java index db1ffe5..a67cd39 100644 --- a/src/backend/src/main/java/com/zioinfo/kintex/security/LoginAttemptService.java +++ b/src/backend/src/main/java/com/zioinfo/kintex/security/LoginAttemptService.java @@ -2,7 +2,11 @@ package com.zioinfo.kintex.security; import com.zioinfo.kintex.common.error.ApiException; import com.zioinfo.kintex.common.error.ErrorCode; +import com.zioinfo.kintex.system.loginhistory.LoginHistoryService; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.stereotype.Service; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; import java.time.OffsetDateTime; import java.util.Map; @@ -10,16 +14,20 @@ import java.util.Map; /** * 로그인 실패 잠금 정책 — 연속 실패 임계 초과 시 {@code locked_until} 설정(계약 §5B-3). * 실패 메시지는 계정 열거를 막기 위해 일반화한다. + * 부가로 로그인 이력(성공/실패)을 best-effort 기록한다(이력 실패가 인증을 막지 않음). */ @Service public class LoginAttemptService { private final AccountSecurityMapper mapper; private final SecurityPolicyProperties props; + private final LoginHistoryService loginHistory; - public LoginAttemptService(AccountSecurityMapper mapper, SecurityPolicyProperties props) { + public LoginAttemptService(AccountSecurityMapper mapper, SecurityPolicyProperties props, + LoginHistoryService loginHistory) { this.mapper = mapper; this.props = props; + this.loginHistory = loginHistory; } /** 현재 잠금 상태면 423(LOCKED). authRow 는 findAuthSecurityByEmail 결과. */ @@ -36,6 +44,8 @@ public class LoginAttemptService { /** 자격 실패 기록 — 임계 초과 시 잠금. */ public void recordFailure(String email, Map authRow) { + // 이력은 계정 존재 여부와 무관하게 기록(마스킹 이메일만) — 침해 탐지 가치. + loginHistory.recordFailure(email, "BAD_CREDENTIAL", clientIp(), userAgent()); if (authRow == null) { return; // 미존재 계정은 상태 변경 없음. } @@ -49,6 +59,32 @@ public class LoginAttemptService { /** 로그인 성공 — 실패 카운트/잠금 해제. */ public void recordSuccess(String userId) { mapper.clearLoginState(userId); + loginHistory.recordSuccess(userId, null, clientIp(), userAgent()); + } + + /** 현재 요청의 클라이언트 IP(X-Forwarded-For 우선). 요청 컨텍스트 없으면 null. */ + private static String clientIp() { + HttpServletRequest req = currentRequest(); + if (req == null) { + return null; + } + String xff = req.getHeader("X-Forwarded-For"); + if (xff != null && !xff.isBlank()) { + return xff.split(",")[0].trim(); + } + return req.getRemoteAddr(); + } + + private static String userAgent() { + HttpServletRequest req = currentRequest(); + return req == null ? null : req.getHeader("User-Agent"); + } + + private static HttpServletRequest currentRequest() { + if (RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes attrs) { + return attrs.getRequest(); + } + return null; } private static int toInt(Object o) { diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyController.java b/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyController.java new file mode 100644 index 0000000..586ff71 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyController.java @@ -0,0 +1,37 @@ +package com.zioinfo.kintex.system.authpolicy; + +import com.zioinfo.kintex.auth.KintexPrincipal; +import com.zioinfo.kintex.common.ApiResponse; +import com.zioinfo.kintex.common.audit.Audited; +import com.zioinfo.kintex.system.SystemAccessGuard; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +/** 시스템관리 — 인증 정책 API. ADMIN 게이트. */ +@RestController +@RequestMapping("/api/admin/auth-policy") +public class AuthPolicyController { + + private final AuthPolicyService service; + private final SystemAccessGuard guard; + + public AuthPolicyController(AuthPolicyService service, SystemAccessGuard guard) { + this.service = service; + this.guard = guard; + } + + @GetMapping + public ApiResponse get(@AuthenticationPrincipal KintexPrincipal principal) { + guard.requireAdmin(principal); + return ApiResponse.ok(service.get()); + } + + @Audited(action = "AUTH_POLICY_SAVE", targetType = "sys_auth_policy") + @PutMapping + public ApiResponse save(@AuthenticationPrincipal KintexPrincipal principal, + @RequestBody AuthPolicySaveRequest req) { + guard.requireAdmin(principal); + service.save(req, principal.userId()); + return ApiResponse.ok(null); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyDto.java b/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyDto.java new file mode 100644 index 0000000..ad9e67f --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyDto.java @@ -0,0 +1,16 @@ +package com.zioinfo.kintex.system.authpolicy; + +/** 인증 정책(비밀번호·로그인 잠금·세션). 시크릿 없음. */ +public record AuthPolicyDto( + Integer pwMinLength, + String pwRequireUpper, + String pwRequireNumber, + String pwRequireSpecial, + Integer pwExpireDays, + Integer loginMaxFail, + Integer lockMinutes, + Integer sessionTimeoutMin, + String updatedAt, + String updatedBy +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyMapper.java b/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyMapper.java new file mode 100644 index 0000000..686e437 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyMapper.java @@ -0,0 +1,30 @@ +package com.zioinfo.kintex.system.authpolicy; + +import org.apache.ibatis.annotations.*; + +import java.util.Map; + +/** 인증 정책 매퍼(sys_auth_policy). 테넌트 싱글턴 1행. */ +@Mapper +public interface AuthPolicyMapper { + + @Select("SELECT pw_min_length AS \"pwMinLength\", pw_require_upper AS \"pwRequireUpper\", " + + "pw_require_number AS \"pwRequireNumber\", pw_require_special AS \"pwRequireSpecial\", " + + "pw_expire_days AS \"pwExpireDays\", login_max_fail AS \"loginMaxFail\", " + + "lock_minutes AS \"lockMinutes\", session_timeout_min AS \"sessionTimeoutMin\", " + + "to_char(updated_at AT TIME ZONE 'UTC','YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') AS \"updatedAt\", " + + "updated_by AS \"updatedBy\" " + + "FROM sys_auth_policy WHERE tenant_id = #{tenantId}") + Map find(@Param("tenantId") String tenantId); + + @Insert("INSERT INTO sys_auth_policy (tenant_id, pw_min_length, pw_require_upper, pw_require_number, " + + "pw_require_special, pw_expire_days, login_max_fail, lock_minutes, session_timeout_min, updated_by) " + + "VALUES (#{tenantId}, #{pwMinLength}, #{pwRequireUpper}, #{pwRequireNumber}, #{pwRequireSpecial}, " + + "#{pwExpireDays}, #{loginMaxFail}, #{lockMinutes}, #{sessionTimeoutMin}, #{updatedBy}) " + + "ON CONFLICT (tenant_id) DO UPDATE SET pw_min_length=EXCLUDED.pw_min_length, " + + "pw_require_upper=EXCLUDED.pw_require_upper, pw_require_number=EXCLUDED.pw_require_number, " + + "pw_require_special=EXCLUDED.pw_require_special, pw_expire_days=EXCLUDED.pw_expire_days, " + + "login_max_fail=EXCLUDED.login_max_fail, lock_minutes=EXCLUDED.lock_minutes, " + + "session_timeout_min=EXCLUDED.session_timeout_min, updated_at=now(), updated_by=EXCLUDED.updated_by") + int upsert(Map p); +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicySaveRequest.java b/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicySaveRequest.java new file mode 100644 index 0000000..b3a4e19 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicySaveRequest.java @@ -0,0 +1,14 @@ +package com.zioinfo.kintex.system.authpolicy; + +/** 인증 정책 저장 본문(서버에서 범위 클램프). */ +public record AuthPolicySaveRequest( + Integer pwMinLength, + String pwRequireUpper, + String pwRequireNumber, + String pwRequireSpecial, + Integer pwExpireDays, + Integer loginMaxFail, + Integer lockMinutes, + Integer sessionTimeoutMin +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyService.java b/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyService.java new file mode 100644 index 0000000..c1ae462 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/authpolicy/AuthPolicyService.java @@ -0,0 +1,63 @@ +package com.zioinfo.kintex.system.authpolicy; + +import com.zioinfo.kintex.tenant.TenantContext; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.Map; + +/** + * 인증 정책 서비스 — 비밀번호 정책·로그인 실패 잠금 임계·세션 타임아웃(관리 조회/변경). + * 실제 잠금 강제는 LoginAttemptService/sys_setting(login.*)가 담당하며, 본 정책은 관리 화면 계약이다 + * (수치 정합: login_max_fail↔login.maxFailedAttempts, lock_minutes↔login.lockMinutes). + */ +@Service +public class AuthPolicyService { + + private final AuthPolicyMapper mapper; + + public AuthPolicyService(AuthPolicyMapper mapper) { + this.mapper = mapper; + } + + public AuthPolicyDto get() { + Map r = mapper.find(TenantContext.currentTenantId()); + if (r == null) { + // 표준 기본값(마이그레이션 시드가 없을 경우의 방어). + return new AuthPolicyDto(8, "N", "Y", "N", 0, 5, 15, 120, null, null); + } + return new AuthPolicyDto( + intv(r.get("pwMinLength")), str(r.get("pwRequireUpper")), str(r.get("pwRequireNumber")), + str(r.get("pwRequireSpecial")), intv(r.get("pwExpireDays")), intv(r.get("loginMaxFail")), + intv(r.get("lockMinutes")), intv(r.get("sessionTimeoutMin")), + str(r.get("updatedAt")), str(r.get("updatedBy"))); + } + + @Transactional + public void save(AuthPolicySaveRequest req, String actorId) { + Map p = new HashMap<>(); + p.put("tenantId", TenantContext.currentTenantId()); + p.put("pwMinLength", clamp(req.pwMinLength(), 4, 64, 8)); + p.put("pwRequireUpper", yn(req.pwRequireUpper())); + p.put("pwRequireNumber", yn(req.pwRequireNumber())); + p.put("pwRequireSpecial", yn(req.pwRequireSpecial())); + p.put("pwExpireDays", clamp(req.pwExpireDays(), 0, 3650, 0)); + p.put("loginMaxFail", clamp(req.loginMaxFail(), 1, 20, 5)); + p.put("lockMinutes", clamp(req.lockMinutes(), 1, 1440, 15)); + p.put("sessionTimeoutMin", clamp(req.sessionTimeoutMin(), 5, 1440, 120)); + p.put("updatedBy", actorId); + mapper.upsert(p); + } + + private static String yn(String v) { return "Y".equalsIgnoreCase(v) ? "Y" : "N"; } + private static int clamp(Integer v, int min, int max, int def) { + int x = v == null ? def : v; + return Math.max(min, Math.min(max, x)); + } + private static String str(Object o) { return o == null ? null : String.valueOf(o); } + private static Integer intv(Object o) { + if (o instanceof Number n) return n.intValue(); + return o == null ? null : Integer.parseInt(String.valueOf(o)); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyController.java b/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyController.java new file mode 100644 index 0000000..ca4d562 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyController.java @@ -0,0 +1,53 @@ +package com.zioinfo.kintex.system.company; + +import com.zioinfo.kintex.auth.KintexPrincipal; +import com.zioinfo.kintex.common.ApiResponse; +import com.zioinfo.kintex.common.PageResponse; +import com.zioinfo.kintex.common.audit.Audited; +import com.zioinfo.kintex.system.SystemAccessGuard; +import jakarta.validation.Valid; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +/** 시스템관리 — 회사(거래처) 관리 API. ADMIN 게이트. 연락처 마스킹. */ +@RestController +@RequestMapping("/api/admin/companies") +public class CompanyController { + + private final CompanyService service; + private final SystemAccessGuard guard; + + public CompanyController(CompanyService service, SystemAccessGuard guard) { + this.service = service; + this.guard = guard; + } + + @GetMapping + public ApiResponse> list( + @AuthenticationPrincipal KintexPrincipal principal, + @RequestParam(required = false) String keyword, + @RequestParam(required = false) String partnerType, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "20") int size) { + guard.requireAdmin(principal); + return ApiResponse.ok(service.list(keyword, partnerType, page, size)); + } + + @Audited(action = "COMPANY_SAVE", targetType = "company") + @PostMapping + public ApiResponse save(@AuthenticationPrincipal KintexPrincipal principal, + @Valid @RequestBody CompanySaveRequest req) { + guard.requireAdmin(principal); + service.save(req); + return ApiResponse.ok(null); + } + + @Audited(action = "COMPANY_DELETE", targetType = "company") + @DeleteMapping("/{id}") + public ApiResponse delete(@AuthenticationPrincipal KintexPrincipal principal, + @PathVariable String id) { + guard.requireAdmin(principal); + service.delete(id); + return ApiResponse.ok(null); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyDto.java b/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyDto.java new file mode 100644 index 0000000..0eb0c33 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyDto.java @@ -0,0 +1,16 @@ +package com.zioinfo.kintex.system.company; + +/** 회사(거래처) 카드. contactTel 은 마스킹되어 전달된다(PII). */ +public record CompanyDto( + String id, + String companyName, + String bizNo, + String ceoName, + String bizType, + String contactName, + String contactTel, + String address, + String partnerType, + String useYn +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyMapper.java b/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyMapper.java new file mode 100644 index 0000000..682a4c7 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyMapper.java @@ -0,0 +1,61 @@ +package com.zioinfo.kintex.system.company; + +import org.apache.ibatis.annotations.*; + +import java.util.List; +import java.util.Map; + +/** 회사(거래처) 매퍼. 테넌트 스코프(V31 표준). */ +@Mapper +public interface CompanyMapper { + + @Select(""" + + """) + List> search(@Param("tenantId") String tenantId, @Param("keyword") String keyword, + @Param("partnerType") String partnerType, + @Param("size") int size, @Param("offset") int offset); + + @Select(""" + + """) + long count(@Param("tenantId") String tenantId, @Param("keyword") String keyword, + @Param("partnerType") String partnerType); + + @Insert("INSERT INTO company (tenant_id, id, company_name, biz_no, ceo_name, biz_type, contact_name, " + + "contact_tel, address, partner_type, use_yn) VALUES (#{tenantId}, #{id}, #{companyName}, #{bizNo}, " + + "#{ceoName}, #{bizType}, #{contactName}, #{contactTel}, #{address}, #{partnerType}, COALESCE(#{useYn},'Y')) " + + "ON CONFLICT (tenant_id, id) DO UPDATE SET company_name=EXCLUDED.company_name, biz_no=EXCLUDED.biz_no, " + + "ceo_name=EXCLUDED.ceo_name, biz_type=EXCLUDED.biz_type, contact_name=EXCLUDED.contact_name, " + + "contact_tel=EXCLUDED.contact_tel, address=EXCLUDED.address, partner_type=EXCLUDED.partner_type, " + + "use_yn=EXCLUDED.use_yn, updated_at=now()") + int upsert(Map p); + + @Delete("DELETE FROM company WHERE tenant_id = #{tenantId} AND id = #{id}") + int delete(@Param("tenantId") String tenantId, @Param("id") String id); +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanySaveRequest.java b/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanySaveRequest.java new file mode 100644 index 0000000..0ee77df --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanySaveRequest.java @@ -0,0 +1,18 @@ +package com.zioinfo.kintex.system.company; + +import jakarta.validation.constraints.NotBlank; + +/** 회사 저장 본문. id 가 있으면 수정, 없으면 신규. */ +public record CompanySaveRequest( + String id, + @NotBlank String companyName, + String bizNo, + String ceoName, + String bizType, + String contactName, + String contactTel, + String address, + String partnerType, + String useYn +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyService.java b/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyService.java new file mode 100644 index 0000000..4588f5b --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/company/CompanyService.java @@ -0,0 +1,68 @@ +package com.zioinfo.kintex.system.company; + +import com.zioinfo.kintex.common.PageResponse; +import com.zioinfo.kintex.common.error.ApiException; +import com.zioinfo.kintex.common.error.ErrorCode; +import com.zioinfo.kintex.common.text.Masking; +import com.zioinfo.kintex.tenant.TenantContext; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** 회사(거래처) 관리 서비스. 연락처는 마스킹 후 응답(§0-3). 테넌트 스코프. */ +@Service +public class CompanyService { + + private final CompanyMapper mapper; + + public CompanyService(CompanyMapper mapper) { + this.mapper = mapper; + } + + public PageResponse list(String keyword, String partnerType, int page, int size) { + int p = Math.max(page, 0); + int s = size <= 0 ? 20 : Math.min(size, 200); + String tenantId = TenantContext.currentTenantId(); + List> rows = mapper.search(tenantId, keyword, partnerType, s, p * s); + long total = mapper.count(tenantId, keyword, partnerType); + return PageResponse.of(rows.stream().map(CompanyService::toDto).toList(), p, s, total); + } + + @Transactional + public void save(CompanySaveRequest req) { + String id = (req.id() == null || req.id().isBlank()) + ? "co-" + UUID.randomUUID().toString().substring(0, 12) : req.id(); + Map pm = new HashMap<>(); + pm.put("tenantId", TenantContext.currentTenantId()); + pm.put("id", id); + pm.put("companyName", req.companyName()); + pm.put("bizNo", req.bizNo()); + pm.put("ceoName", req.ceoName()); + pm.put("bizType", req.bizType()); + pm.put("contactName", req.contactName()); + pm.put("contactTel", req.contactTel()); + pm.put("address", req.address()); + pm.put("partnerType", req.partnerType()); + pm.put("useYn", req.useYn()); + mapper.upsert(pm); + } + + @Transactional + public void delete(String id) { + if (mapper.delete(TenantContext.currentTenantId(), id) == 0) { + throw new ApiException(ErrorCode.NOT_FOUND); + } + } + + private static CompanyDto toDto(Map r) { + return new CompanyDto( + str(r.get("id")), str(r.get("companyName")), str(r.get("bizNo")), str(r.get("ceoName")), + str(r.get("bizType")), str(r.get("contactName")), Masking.maskPhone(str(r.get("contactTel"))), + str(r.get("address")), str(r.get("partnerType")), str(r.get("useYn"))); + } + private static String str(Object o) { return o == null ? null : String.valueOf(o); } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptController.java b/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptController.java new file mode 100644 index 0000000..0aec376 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptController.java @@ -0,0 +1,49 @@ +package com.zioinfo.kintex.system.dept; + +import com.zioinfo.kintex.auth.KintexPrincipal; +import com.zioinfo.kintex.common.ApiResponse; +import com.zioinfo.kintex.common.audit.Audited; +import com.zioinfo.kintex.system.SystemAccessGuard; +import jakarta.validation.Valid; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** 시스템관리 — 조직(부서 트리) 관리 API. ADMIN 게이트. */ +@RestController +@RequestMapping("/api/admin/depts") +public class DeptController { + + private final DeptService service; + private final SystemAccessGuard guard; + + public DeptController(DeptService service, SystemAccessGuard guard) { + this.service = service; + this.guard = guard; + } + + @GetMapping + public ApiResponse> tree(@AuthenticationPrincipal KintexPrincipal principal) { + guard.requireAdmin(principal); + return ApiResponse.ok(service.tree()); + } + + @Audited(action = "DEPT_SAVE", targetType = "dept") + @PostMapping + public ApiResponse save(@AuthenticationPrincipal KintexPrincipal principal, + @Valid @RequestBody DeptSaveRequest req) { + guard.requireAdmin(principal); + service.save(req); + return ApiResponse.ok(null); + } + + @Audited(action = "DEPT_DELETE", targetType = "dept") + @DeleteMapping("/{id}") + public ApiResponse delete(@AuthenticationPrincipal KintexPrincipal principal, + @PathVariable String id) { + guard.requireAdmin(principal); + service.delete(id); + return ApiResponse.ok(null); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptDto.java b/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptDto.java new file mode 100644 index 0000000..c45570f --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptDto.java @@ -0,0 +1,14 @@ +package com.zioinfo.kintex.system.dept; + +import java.util.List; + +/** 부서 노드(트리). children 은 sort_order→id 순 중첩. */ +public record DeptDto( + String id, + String deptName, + String parentId, + Integer sortOrder, + String useYn, + List children +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptMapper.java b/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptMapper.java new file mode 100644 index 0000000..dd8b023 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptMapper.java @@ -0,0 +1,28 @@ +package com.zioinfo.kintex.system.dept; + +import org.apache.ibatis.annotations.*; + +import java.util.List; +import java.util.Map; + +/** 부서 매퍼(dept). 테넌트 스코프(V31 표준). */ +@Mapper +public interface DeptMapper { + + @Select("SELECT id, dept_name AS \"deptName\", parent_id AS \"parentId\", " + + "sort_order AS \"sortOrder\", use_yn AS \"useYn\" " + + "FROM dept WHERE tenant_id = #{tenantId} ORDER BY sort_order, id") + List> findAll(@Param("tenantId") String tenantId); + + @Insert("INSERT INTO dept (tenant_id, id, dept_name, parent_id, sort_order, use_yn) " + + "VALUES (#{tenantId}, #{id}, #{deptName}, #{parentId}, COALESCE(#{sortOrder},0), COALESCE(#{useYn},'Y')) " + + "ON CONFLICT (tenant_id, id) DO UPDATE SET dept_name=EXCLUDED.dept_name, parent_id=EXCLUDED.parent_id, " + + "sort_order=EXCLUDED.sort_order, use_yn=EXCLUDED.use_yn, updated_at=now()") + int upsert(Map p); + + @Delete("DELETE FROM dept WHERE tenant_id = #{tenantId} AND id = #{id}") + int delete(@Param("tenantId") String tenantId, @Param("id") String id); + + @Select("SELECT count(*) FROM dept WHERE tenant_id = #{tenantId} AND parent_id = #{id}") + int countChildren(@Param("tenantId") String tenantId, @Param("id") String id); +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptSaveRequest.java b/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptSaveRequest.java new file mode 100644 index 0000000..865efaa --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptSaveRequest.java @@ -0,0 +1,13 @@ +package com.zioinfo.kintex.system.dept; + +import jakarta.validation.constraints.NotBlank; + +/** 부서 저장 본문. id 가 있으면 수정, 없으면 신규(백엔드 upsert). */ +public record DeptSaveRequest( + String id, + @NotBlank String deptName, + String parentId, + Integer sortOrder, + String useYn +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptService.java b/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptService.java new file mode 100644 index 0000000..6062515 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/dept/DeptService.java @@ -0,0 +1,84 @@ +package com.zioinfo.kintex.system.dept; + +import com.zioinfo.kintex.common.error.ApiException; +import com.zioinfo.kintex.common.error.ErrorCode; +import com.zioinfo.kintex.tenant.TenantContext; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** 조직 — 부서 트리 서비스. 테넌트 컨텍스트로 스코프(§8-2). */ +@Service +public class DeptService { + + private final DeptMapper mapper; + + public DeptService(DeptMapper mapper) { + this.mapper = mapper; + } + + /** 전체 부서를 트리로 조립(루트=parentId null 또는 미존재 부모). */ + public List tree() { + String tenantId = TenantContext.currentTenantId(); + List> rows = mapper.findAll(tenantId); + Map> childrenOf = new LinkedHashMap<>(); + Map> byId = new LinkedHashMap<>(); + for (Map r : rows) { + byId.put(str(r.get("id")), r); + } + List roots = new ArrayList<>(); + // 재귀 없이 childrenOf 맵으로 조립(rows 순서=sort_order,id → 안정 정렬). + for (Map r : rows) { + String id = str(r.get("id")); + String parentId = str(r.get("parentId")); + List kids = childrenOf.computeIfAbsent(id, k -> new ArrayList<>()); + DeptDto node = new DeptDto(id, str(r.get("deptName")), parentId, + intv(r.get("sortOrder")), str(r.get("useYn")), kids); + if (parentId == null || !byId.containsKey(parentId)) { + roots.add(node); + } else { + childrenOf.computeIfAbsent(parentId, k -> new ArrayList<>()).add(node); + } + } + return roots; + } + + @Transactional + public void save(DeptSaveRequest req) { + Map p = new java.util.HashMap<>(); + String id = (req.id() == null || req.id().isBlank()) + ? "dept-" + UUID.randomUUID().toString().substring(0, 12) : req.id(); + if (id.equals(req.parentId())) { + throw new ApiException(ErrorCode.VALIDATION, "부모 부서를 자기 자신으로 지정할 수 없습니다."); + } + p.put("tenantId", TenantContext.currentTenantId()); + p.put("id", id); + p.put("deptName", req.deptName()); + p.put("parentId", (req.parentId() == null || req.parentId().isBlank()) ? null : req.parentId()); + p.put("sortOrder", req.sortOrder()); + p.put("useYn", req.useYn()); + mapper.upsert(p); + } + + @Transactional + public void delete(String id) { + String tenantId = TenantContext.currentTenantId(); + if (mapper.countChildren(tenantId, id) > 0) { + throw new ApiException(ErrorCode.CONFLICT, "하위 부서가 있어 삭제할 수 없습니다."); + } + if (mapper.delete(tenantId, id) == 0) { + throw new ApiException(ErrorCode.NOT_FOUND); + } + } + + private static String str(Object o) { return o == null ? null : String.valueOf(o); } + private static Integer intv(Object o) { + if (o instanceof Number n) return n.intValue(); + return o == null ? 0 : Integer.parseInt(String.valueOf(o)); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogController.java b/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogController.java new file mode 100644 index 0000000..853c95d --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogController.java @@ -0,0 +1,32 @@ +package com.zioinfo.kintex.system.errorlog; + +import com.zioinfo.kintex.auth.KintexPrincipal; +import com.zioinfo.kintex.common.ApiResponse; +import com.zioinfo.kintex.common.PageResponse; +import com.zioinfo.kintex.system.SystemAccessGuard; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +/** 시스템관리 — 오류 로그 조회 API. ADMIN 게이트. 읽기 전용(요약 1줄). */ +@RestController +@RequestMapping("/api/admin/error-log") +public class ErrorLogController { + + private final ErrorLogService service; + private final SystemAccessGuard guard; + + public ErrorLogController(ErrorLogService service, SystemAccessGuard guard) { + this.service = service; + this.guard = guard; + } + + @GetMapping + public ApiResponse> list( + @AuthenticationPrincipal KintexPrincipal principal, + @RequestParam(required = false) String errorCode, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "20") int size) { + guard.requireAdmin(principal); + return ApiResponse.ok(service.list(errorCode, page, size)); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogDto.java b/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogDto.java new file mode 100644 index 0000000..ad3240e --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogDto.java @@ -0,0 +1,13 @@ +package com.zioinfo.kintex.system.errorlog; + +/** 오류 로그 행(조회). summary 는 1줄 요약(스택트레이스 미포함, §0-3). */ +public record ErrorLogDto( + long id, + String errorCode, + String summary, + String path, + String method, + String actorId, + String createdAt +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogMapper.java b/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogMapper.java new file mode 100644 index 0000000..4f4e85e --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogMapper.java @@ -0,0 +1,42 @@ +package com.zioinfo.kintex.system.errorlog; + +import org.apache.ibatis.annotations.*; + +import java.util.List; +import java.util.Map; + +/** 오류 로그 매퍼(error_log). 요약 1줄만 저장(스택트레이스 금지). 테넌트 스코프. */ +@Mapper +public interface ErrorLogMapper { + + @Insert("INSERT INTO error_log (tenant_id, error_code, summary, path, method, actor_id) " + + "VALUES (#{tenantId}, #{errorCode}, #{summary}, #{path}, #{method}, #{actorId})") + int insert(Map p); + + @Select(""" + + """) + List> search(@Param("tenantId") String tenantId, @Param("errorCode") String errorCode, + @Param("size") int size, @Param("offset") int offset); + + @Select(""" + + """) + long count(@Param("tenantId") String tenantId, @Param("errorCode") String errorCode); +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogService.java b/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogService.java new file mode 100644 index 0000000..52fa560 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/errorlog/ErrorLogService.java @@ -0,0 +1,65 @@ +package com.zioinfo.kintex.system.errorlog; + +import com.zioinfo.kintex.common.PageResponse; +import com.zioinfo.kintex.tenant.TenantContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 오류 로그 서비스 — 기록(best-effort)·조회. 저장은 요약 1줄만(스택트레이스·민감정보 금지, §0-3). + * 기록 실패가 원 예외 응답을 막지 않도록 예외를 삼킨다. + */ +@Service +public class ErrorLogService { + + private static final Logger log = LoggerFactory.getLogger(ErrorLogService.class); + private final ErrorLogMapper mapper; + + public ErrorLogService(ErrorLogMapper mapper) { + this.mapper = mapper; + } + + /** 예외 요약 기록. summary 는 호출자가 스택 제외한 1줄 요약을 넘긴다. */ + public void record(String errorCode, String summary, String path, String method, String actorId) { + try { + Map p = new HashMap<>(); + p.put("tenantId", TenantContext.currentTenantId()); + p.put("errorCode", errorCode); + p.put("summary", trunc(summary, 500)); + p.put("path", trunc(path, 300)); + p.put("method", method); + p.put("actorId", actorId); + mapper.insert(p); + } catch (Exception e) { + log.warn("[ERROR_LOG] record skipped: {}", e.getClass().getSimpleName()); + } + } + + public PageResponse list(String errorCode, int page, int size) { + int p = Math.max(page, 0); + int s = size <= 0 ? 20 : Math.min(size, 200); + String tenantId = TenantContext.currentTenantId(); + List> rows = mapper.search(tenantId, errorCode, s, p * s); + long total = mapper.count(tenantId, errorCode); + return PageResponse.of(rows.stream().map(ErrorLogService::toDto).toList(), p, s, total); + } + + private static ErrorLogDto toDto(Map r) { + return new ErrorLogDto(lng(r.get("id")), str(r.get("errorCode")), str(r.get("summary")), + str(r.get("path")), str(r.get("method")), str(r.get("actorId")), str(r.get("createdAt"))); + } + private static String trunc(String v, int max) { + if (v == null) return null; + return v.length() <= max ? v : v.substring(0, max); + } + private static String str(Object o) { return o == null ? null : String.valueOf(o); } + private static long lng(Object o) { + if (o instanceof Number n) return n.longValue(); + return o == null ? 0L : Long.parseLong(String.valueOf(o)); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/InfraConfigDto.java b/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/InfraConfigDto.java new file mode 100644 index 0000000..2613439 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/InfraConfigDto.java @@ -0,0 +1,11 @@ +package com.zioinfo.kintex.system.infraconfig; + +/** 설정 항목(메일/알림). secretYn='Y' 이면 settingValue 는 마스킹(********)되어 전달된다. */ +public record InfraConfigDto( + String settingKey, + String settingValue, + String valueType, + String description, + String secretYn +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/InfraConfigService.java b/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/InfraConfigService.java new file mode 100644 index 0000000..a311191 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/InfraConfigService.java @@ -0,0 +1,75 @@ +package com.zioinfo.kintex.system.infraconfig; + +import com.zioinfo.kintex.common.error.ApiException; +import com.zioinfo.kintex.common.error.ErrorCode; +import com.zioinfo.kintex.system.setting.SettingMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 메일/알림 설정 서비스 — sys_setting 의 mail. / notify. 프리픽스 항목을 조회/부분변경한다. + * 시크릿(secret_yn='Y')은 응답 마스킹, 저장 시 마스킹 값은 미변경 처리(§0-3, 시크릿 미노출·미덮어쓰기). + */ +@Service +public class InfraConfigService { + + private static final String MASK = "********"; + private final SettingMapper mapper; + + public InfraConfigService(SettingMapper mapper) { + this.mapper = mapper; + } + + public List listByPrefix(String prefix) { + return mapper.findAll().stream() + .filter(r -> str(r.get("settingKey")) != null && str(r.get("settingKey")).startsWith(prefix)) + .map(InfraConfigService::toMaskedDto) + .toList(); + } + + @Transactional + public void update(String prefix, InfraConfigUpdateRequest req, String actorId) { + if (req.items() == null) { + return; + } + for (InfraConfigUpdateRequest.Item it : req.items()) { + String key = it.settingKey(); + if (key == null || !key.startsWith(prefix)) { + throw new ApiException(ErrorCode.VALIDATION, "허용되지 않은 설정 키입니다."); + } + Map existing = mapper.findByKey(key); + if (existing == null) { + throw new ApiException(ErrorCode.NOT_FOUND, "설정 항목이 없습니다: " + key); + } + String secretYn = str(existing.get("secretYn")); + String value = it.settingValue(); + // 마스킹 그대로 온 시크릿은 미변경(원문 보존). + if ("Y".equals(secretYn) && MASK.equals(value)) { + continue; + } + Map p = new HashMap<>(); + p.put("settingKey", key); + p.put("settingValue", value); + p.put("valueType", str(existing.get("valueType"))); + p.put("description", str(existing.get("description"))); + p.put("secretYn", secretYn); + p.put("updatedBy", actorId); + mapper.upsert(p); + } + } + + private static InfraConfigDto toMaskedDto(Map r) { + String secretYn = str(r.get("secretYn")); + String value = str(r.get("settingValue")); + if ("Y".equals(secretYn) && value != null && !value.isEmpty()) { + value = MASK; + } + return new InfraConfigDto(str(r.get("settingKey")), value, str(r.get("valueType")), + str(r.get("description")), secretYn); + } + private static String str(Object o) { return o == null ? null : String.valueOf(o); } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/InfraConfigUpdateRequest.java b/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/InfraConfigUpdateRequest.java new file mode 100644 index 0000000..caef0dc --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/InfraConfigUpdateRequest.java @@ -0,0 +1,11 @@ +package com.zioinfo.kintex.system.infraconfig; + +import java.util.List; + +/** 메일/알림 설정 부분 변경 본문. 마스킹(********) 값은 미변경으로 간주(시크릿 보존). */ +public record InfraConfigUpdateRequest( + List items +) { + public record Item(String settingKey, String settingValue) { + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/MailConfigController.java b/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/MailConfigController.java new file mode 100644 index 0000000..e31a9f5 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/MailConfigController.java @@ -0,0 +1,40 @@ +package com.zioinfo.kintex.system.infraconfig; + +import com.zioinfo.kintex.auth.KintexPrincipal; +import com.zioinfo.kintex.common.ApiResponse; +import com.zioinfo.kintex.common.audit.Audited; +import com.zioinfo.kintex.system.SystemAccessGuard; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** 시스템관리 — 메일(SMTP) 설정 조회/변경 API. ADMIN 게이트. 시크릿 마스킹. */ +@RestController +@RequestMapping("/api/admin/mail-config") +public class MailConfigController { + + private static final String PREFIX = "mail."; + private final InfraConfigService service; + private final SystemAccessGuard guard; + + public MailConfigController(InfraConfigService service, SystemAccessGuard guard) { + this.service = service; + this.guard = guard; + } + + @GetMapping + public ApiResponse> list(@AuthenticationPrincipal KintexPrincipal principal) { + guard.requireAdmin(principal); + return ApiResponse.ok(service.listByPrefix(PREFIX)); + } + + @Audited(action = "MAIL_CONFIG_SAVE", targetType = "sys_setting") + @PutMapping + public ApiResponse update(@AuthenticationPrincipal KintexPrincipal principal, + @RequestBody InfraConfigUpdateRequest req) { + guard.requireAdmin(principal); + service.update(PREFIX, req, principal.userId()); + return ApiResponse.ok(null); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/NotifyConfigController.java b/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/NotifyConfigController.java new file mode 100644 index 0000000..3038c17 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/infraconfig/NotifyConfigController.java @@ -0,0 +1,40 @@ +package com.zioinfo.kintex.system.infraconfig; + +import com.zioinfo.kintex.auth.KintexPrincipal; +import com.zioinfo.kintex.common.ApiResponse; +import com.zioinfo.kintex.common.audit.Audited; +import com.zioinfo.kintex.system.SystemAccessGuard; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** 시스템관리 — 알림 채널 설정 조회/변경 API. ADMIN 게이트. 채널 on/off. */ +@RestController +@RequestMapping("/api/admin/notify-config") +public class NotifyConfigController { + + private static final String PREFIX = "notify."; + private final InfraConfigService service; + private final SystemAccessGuard guard; + + public NotifyConfigController(InfraConfigService service, SystemAccessGuard guard) { + this.service = service; + this.guard = guard; + } + + @GetMapping + public ApiResponse> list(@AuthenticationPrincipal KintexPrincipal principal) { + guard.requireAdmin(principal); + return ApiResponse.ok(service.listByPrefix(PREFIX)); + } + + @Audited(action = "NOTIFY_CONFIG_SAVE", targetType = "sys_setting") + @PutMapping + public ApiResponse update(@AuthenticationPrincipal KintexPrincipal principal, + @RequestBody InfraConfigUpdateRequest req) { + guard.requireAdmin(principal); + service.update(PREFIX, req, principal.userId()); + return ApiResponse.ok(null); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryController.java b/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryController.java new file mode 100644 index 0000000..a490246 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryController.java @@ -0,0 +1,33 @@ +package com.zioinfo.kintex.system.loginhistory; + +import com.zioinfo.kintex.auth.KintexPrincipal; +import com.zioinfo.kintex.common.ApiResponse; +import com.zioinfo.kintex.common.PageResponse; +import com.zioinfo.kintex.system.SystemAccessGuard; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +/** 시스템관리 — 로그인 이력(접속 세션) 조회 API. ADMIN 게이트. 읽기 전용. */ +@RestController +@RequestMapping("/api/admin/login-history") +public class LoginHistoryController { + + private final LoginHistoryService service; + private final SystemAccessGuard guard; + + public LoginHistoryController(LoginHistoryService service, SystemAccessGuard guard) { + this.service = service; + this.guard = guard; + } + + @GetMapping + public ApiResponse> list( + @AuthenticationPrincipal KintexPrincipal principal, + @RequestParam(required = false) String result, + @RequestParam(required = false) String userId, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "20") int size) { + guard.requireAdmin(principal); + return ApiResponse.ok(service.list(result, userId, page, size)); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryDto.java b/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryDto.java new file mode 100644 index 0000000..788d79c --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryDto.java @@ -0,0 +1,14 @@ +package com.zioinfo.kintex.system.loginhistory; + +/** 로그인 이력 행(조회). 이메일/IP 는 마스킹되어 저장·전달된다(§0-3). */ +public record LoginHistoryDto( + long id, + String userId, + String emailMasked, + String result, + String failReason, + String ipMasked, + String userAgent, + String createdAt +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryMapper.java b/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryMapper.java new file mode 100644 index 0000000..595ec6c --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryMapper.java @@ -0,0 +1,47 @@ +package com.zioinfo.kintex.system.loginhistory; + +import org.apache.ibatis.annotations.*; + +import java.util.List; +import java.util.Map; + +/** 로그인 이력 매퍼(login_history). 저장 값은 마스킹만(원문 금지). 테넌트 스코프. */ +@Mapper +public interface LoginHistoryMapper { + + @Insert("INSERT INTO login_history (tenant_id, user_id, email_masked, result, fail_reason, ip_masked, user_agent) " + + "VALUES (#{tenantId}, #{userId}, #{emailMasked}, #{result}, #{failReason}, #{ipMasked}, #{userAgent})") + int insert(Map p); + + @Select(""" + + """) + List> search(@Param("tenantId") String tenantId, @Param("result") String result, + @Param("userId") String userId, + @Param("size") int size, @Param("offset") int offset); + + @Select(""" + + """) + long count(@Param("tenantId") String tenantId, @Param("result") String result, + @Param("userId") String userId); +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryService.java b/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryService.java new file mode 100644 index 0000000..79d8d03 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/loginhistory/LoginHistoryService.java @@ -0,0 +1,78 @@ +package com.zioinfo.kintex.system.loginhistory; + +import com.zioinfo.kintex.common.PageResponse; +import com.zioinfo.kintex.common.text.Masking; +import com.zioinfo.kintex.tenant.TenantContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 로그인 이력 서비스 — 기록(best-effort)·조회. 기록은 인증 흐름을 절대 깨지 않는다(예외 삼킴). + * 저장 값은 이메일/IP 마스킹만(원문 금지, §0-3). + */ +@Service +public class LoginHistoryService { + + private static final Logger log = LoggerFactory.getLogger(LoginHistoryService.class); + private final LoginHistoryMapper mapper; + + public LoginHistoryService(LoginHistoryMapper mapper) { + this.mapper = mapper; + } + + /** 로그인 성공 기록(best-effort). ip 는 원문을 받아 마스킹 저장. */ + public void recordSuccess(String userId, String email, String ip, String userAgent) { + record(userId, email, "SUCCESS", null, ip, userAgent); + } + + /** 로그인 실패 기록(best-effort). reason 은 짧은 요약 코드. */ + public void recordFailure(String email, String reason, String ip, String userAgent) { + record(null, email, "FAIL", reason, ip, userAgent); + } + + private void record(String userId, String email, String result, String reason, String ip, String userAgent) { + try { + Map p = new HashMap<>(); + p.put("tenantId", TenantContext.currentTenantId()); + p.put("userId", userId); + p.put("emailMasked", Masking.maskEmail(email)); + p.put("result", result); + p.put("failReason", reason); + p.put("ipMasked", Masking.maskIp(ip)); + p.put("userAgent", trunc(userAgent, 300)); + mapper.insert(p); + } catch (Exception e) { + // 이력 기록 실패가 로그인 자체를 막아선 안 된다. + log.warn("[LOGIN_HISTORY] record skipped: {}", e.getClass().getSimpleName()); + } + } + + public PageResponse list(String result, String userId, int page, int size) { + int p = Math.max(page, 0); + int s = size <= 0 ? 20 : Math.min(size, 200); + String tenantId = TenantContext.currentTenantId(); + List> rows = mapper.search(tenantId, result, userId, s, p * s); + long total = mapper.count(tenantId, result, userId); + return PageResponse.of(rows.stream().map(LoginHistoryService::toDto).toList(), p, s, total); + } + + private static LoginHistoryDto toDto(Map r) { + return new LoginHistoryDto( + lng(r.get("id")), str(r.get("userId")), str(r.get("emailMasked")), str(r.get("result")), + str(r.get("failReason")), str(r.get("ipMasked")), str(r.get("userAgent")), str(r.get("createdAt"))); + } + private static String trunc(String v, int max) { + if (v == null) return null; + return v.length() <= max ? v : v.substring(0, max); + } + private static String str(Object o) { return o == null ? null : String.valueOf(o); } + private static long lng(Object o) { + if (o instanceof Number n) return n.longValue(); + return o == null ? 0L : Long.parseLong(String.valueOf(o)); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramController.java b/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramController.java new file mode 100644 index 0000000..30ea4b1 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramController.java @@ -0,0 +1,51 @@ +package com.zioinfo.kintex.system.program; + +import com.zioinfo.kintex.auth.KintexPrincipal; +import com.zioinfo.kintex.common.ApiResponse; +import com.zioinfo.kintex.common.audit.Audited; +import com.zioinfo.kintex.system.SystemAccessGuard; +import jakarta.validation.Valid; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** 시스템관리 — 프로그램(화면) 등록부 API. ADMIN 게이트. */ +@RestController +@RequestMapping("/api/admin/programs") +public class ProgramController { + + private final ProgramService service; + private final SystemAccessGuard guard; + + public ProgramController(ProgramService service, SystemAccessGuard guard) { + this.service = service; + this.guard = guard; + } + + @GetMapping + public ApiResponse> list(@AuthenticationPrincipal KintexPrincipal principal, + @RequestParam(required = false) String keyword, + @RequestParam(required = false) String category) { + guard.requireAdmin(principal); + return ApiResponse.ok(service.list(keyword, category)); + } + + @Audited(action = "PROGRAM_SAVE", targetType = "sys_program") + @PostMapping + public ApiResponse save(@AuthenticationPrincipal KintexPrincipal principal, + @Valid @RequestBody ProgramSaveRequest req) { + guard.requireAdmin(principal); + service.save(req); + return ApiResponse.ok(null); + } + + @Audited(action = "PROGRAM_DELETE", targetType = "sys_program") + @DeleteMapping("/{id}") + public ApiResponse delete(@AuthenticationPrincipal KintexPrincipal principal, + @PathVariable String id) { + guard.requireAdmin(principal); + service.delete(id); + return ApiResponse.ok(null); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramDto.java b/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramDto.java new file mode 100644 index 0000000..60b3411 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramDto.java @@ -0,0 +1,12 @@ +package com.zioinfo.kintex.system.program; + +/** 프로그램(화면) 등록부 항목. */ +public record ProgramDto( + String id, + String programName, + String programType, + String programUrl, + String category, + String useYn +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramMapper.java b/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramMapper.java new file mode 100644 index 0000000..260dbf2 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramMapper.java @@ -0,0 +1,40 @@ +package com.zioinfo.kintex.system.program; + +import org.apache.ibatis.annotations.*; + +import java.util.List; +import java.util.Map; + +/** 프로그램(화면) 매퍼(sys_program). 테넌트 스코프. */ +@Mapper +public interface ProgramMapper { + + @Select(""" + + """) + List> findAll(@Param("tenantId") String tenantId, + @Param("keyword") String keyword, @Param("category") String category); + + @Insert("INSERT INTO sys_program (tenant_id, id, program_name, program_type, program_url, category, use_yn) " + + "VALUES (#{tenantId}, #{id}, #{programName}, COALESCE(#{programType},'SCREEN'), #{programUrl}, " + + "#{category}, COALESCE(#{useYn},'Y')) " + + "ON CONFLICT (tenant_id, id) DO UPDATE SET program_name=EXCLUDED.program_name, " + + "program_type=EXCLUDED.program_type, program_url=EXCLUDED.program_url, " + + "category=EXCLUDED.category, use_yn=EXCLUDED.use_yn, updated_at=now()") + int upsert(Map p); + + @Delete("DELETE FROM sys_program WHERE tenant_id = #{tenantId} AND id = #{id}") + int delete(@Param("tenantId") String tenantId, @Param("id") String id); +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramSaveRequest.java b/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramSaveRequest.java new file mode 100644 index 0000000..bee1767 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramSaveRequest.java @@ -0,0 +1,14 @@ +package com.zioinfo.kintex.system.program; + +import jakarta.validation.constraints.NotBlank; + +/** 프로그램 저장 본문. id 가 있으면 수정, 없으면 신규. */ +public record ProgramSaveRequest( + String id, + @NotBlank String programName, + String programType, + String programUrl, + String category, + String useYn +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramService.java b/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramService.java new file mode 100644 index 0000000..ea1b7f0 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/program/ProgramService.java @@ -0,0 +1,56 @@ +package com.zioinfo.kintex.system.program; + +import com.zioinfo.kintex.common.error.ApiException; +import com.zioinfo.kintex.common.error.ErrorCode; +import com.zioinfo.kintex.tenant.TenantContext; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** 프로그램(화면) 등록부 서비스. 테넌트 스코프. */ +@Service +public class ProgramService { + + private final ProgramMapper mapper; + + public ProgramService(ProgramMapper mapper) { + this.mapper = mapper; + } + + public List list(String keyword, String category) { + return mapper.findAll(TenantContext.currentTenantId(), keyword, category).stream() + .map(ProgramService::toDto).toList(); + } + + @Transactional + public void save(ProgramSaveRequest req) { + String id = (req.id() == null || req.id().isBlank()) + ? "prg-" + UUID.randomUUID().toString().substring(0, 12) : req.id(); + Map p = new HashMap<>(); + p.put("tenantId", TenantContext.currentTenantId()); + p.put("id", id); + p.put("programName", req.programName()); + p.put("programType", req.programType()); + p.put("programUrl", req.programUrl()); + p.put("category", req.category()); + p.put("useYn", req.useYn()); + mapper.upsert(p); + } + + @Transactional + public void delete(String id) { + if (mapper.delete(TenantContext.currentTenantId(), id) == 0) { + throw new ApiException(ErrorCode.NOT_FOUND); + } + } + + private static ProgramDto toDto(Map r) { + return new ProgramDto(str(r.get("id")), str(r.get("programName")), str(r.get("programType")), + str(r.get("programUrl")), str(r.get("category")), str(r.get("useYn"))); + } + private static String str(Object o) { return o == null ? null : String.valueOf(o); } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuController.java b/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuController.java new file mode 100644 index 0000000..f429c7c --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuController.java @@ -0,0 +1,41 @@ +package com.zioinfo.kintex.system.rolemenu; + +import com.zioinfo.kintex.auth.KintexPrincipal; +import com.zioinfo.kintex.common.ApiResponse; +import com.zioinfo.kintex.common.audit.Audited; +import com.zioinfo.kintex.system.SystemAccessGuard; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** 시스템관리 — 역할별 메뉴 접근 매핑 API. ADMIN 게이트. 기존 역할/권한(rolePerm)과 직교. */ +@RestController +@RequestMapping("/api/admin/roles/{roleCode}/menus") +public class RoleMenuController { + + private final RoleMenuService service; + private final SystemAccessGuard guard; + + public RoleMenuController(RoleMenuService service, SystemAccessGuard guard) { + this.service = service; + this.guard = guard; + } + + @GetMapping + public ApiResponse> list(@AuthenticationPrincipal KintexPrincipal principal, + @PathVariable String roleCode) { + guard.requireAdmin(principal); + return ApiResponse.ok(service.listByRole(roleCode)); + } + + @Audited(action = "ROLE_MENU_SAVE", targetType = "sys_role_menu") + @PostMapping + public ApiResponse save(@AuthenticationPrincipal KintexPrincipal principal, + @PathVariable String roleCode, + @RequestBody RoleMenuSaveRequest req) { + guard.requireAdmin(principal); + service.save(roleCode, req); + return ApiResponse.ok(null); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuDto.java b/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuDto.java new file mode 100644 index 0000000..3e113e6 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuDto.java @@ -0,0 +1,13 @@ +package com.zioinfo.kintex.system.rolemenu; + +/** 역할-메뉴 매핑 행. mapped=false 면 아직 미부여(read/write 기본값). */ +public record RoleMenuDto( + String menuId, + String menuName, + String parentId, + Integer sortOrder, + boolean mapped, + String readYn, + String writeYn +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuMapper.java b/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuMapper.java new file mode 100644 index 0000000..42b27dd --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuMapper.java @@ -0,0 +1,33 @@ +package com.zioinfo.kintex.system.rolemenu; + +import org.apache.ibatis.annotations.*; + +import java.util.List; +import java.util.Map; + +/** 역할-메뉴 매핑 매퍼(sys_role_menu). 전역 규약(sys_menu·sys_role 참조). */ +@Mapper +public interface RoleMenuMapper { + + /** 전체 메뉴 + 해당 역할의 매핑 상태(LEFT JOIN). */ + @Select("SELECT m.id AS \"menuId\", m.menu_name AS \"menuName\", m.parent_id AS \"parentId\", " + + "m.sort_order AS \"sortOrder\", " + + "(rm.menu_id IS NOT NULL) AS \"mapped\", " + + "COALESCE(rm.read_yn,'N') AS \"readYn\", COALESCE(rm.write_yn,'N') AS \"writeYn\" " + + "FROM sys_menu m " + + "LEFT JOIN sys_role_menu rm ON rm.menu_id = m.id AND rm.role_code = #{roleCode} " + + "ORDER BY m.sort_order, m.id") + List> findByRole(@Param("roleCode") String roleCode); + + @Delete("DELETE FROM sys_role_menu WHERE role_code = #{roleCode}") + int clear(@Param("roleCode") String roleCode); + + @Insert("INSERT INTO sys_role_menu (role_code, menu_id, read_yn, write_yn) " + + "VALUES (#{roleCode}, #{menuId}, COALESCE(#{readYn},'Y'), COALESCE(#{writeYn},'N')) " + + "ON CONFLICT (role_code, menu_id) DO UPDATE SET read_yn=EXCLUDED.read_yn, write_yn=EXCLUDED.write_yn") + int add(@Param("roleCode") String roleCode, @Param("menuId") String menuId, + @Param("readYn") String readYn, @Param("writeYn") String writeYn); + + @Select("SELECT COUNT(*) FROM sys_role WHERE role_code = #{roleCode}") + int roleExists(@Param("roleCode") String roleCode); +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuSaveRequest.java b/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuSaveRequest.java new file mode 100644 index 0000000..b85db3f --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuSaveRequest.java @@ -0,0 +1,12 @@ +package com.zioinfo.kintex.system.rolemenu; + +import java.util.List; + +/** 역할별 메뉴 매핑 저장 본문. 목록에 없는 메뉴는 매핑 해제된다(전체 치환). */ +public record RoleMenuSaveRequest( + List menus +) { + /** 매핑 항목. readYn/writeYn 미지정 시 read=Y·write=N. */ + public record Entry(String menuId, String readYn, String writeYn) { + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuService.java b/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuService.java new file mode 100644 index 0000000..15ed540 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/rolemenu/RoleMenuService.java @@ -0,0 +1,62 @@ +package com.zioinfo.kintex.system.rolemenu; + +import com.zioinfo.kintex.common.error.ApiException; +import com.zioinfo.kintex.common.error.ErrorCode; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +/** 역할-메뉴 매핑 서비스. 저장은 전체 치환(clear→insert). */ +@Service +public class RoleMenuService { + + private final RoleMenuMapper mapper; + + public RoleMenuService(RoleMenuMapper mapper) { + this.mapper = mapper; + } + + public List listByRole(String roleCode) { + if (mapper.roleExists(roleCode) == 0) { + throw new ApiException(ErrorCode.NOT_FOUND, "역할을 찾을 수 없습니다."); + } + return mapper.findByRole(roleCode).stream().map(RoleMenuService::toDto).toList(); + } + + @Transactional + public void save(String roleCode, RoleMenuSaveRequest req) { + if (mapper.roleExists(roleCode) == 0) { + throw new ApiException(ErrorCode.NOT_FOUND, "역할을 찾을 수 없습니다."); + } + mapper.clear(roleCode); + if (req.menus() != null) { + for (RoleMenuSaveRequest.Entry e : req.menus()) { + if (e.menuId() == null || e.menuId().isBlank()) { + continue; + } + mapper.add(roleCode, e.menuId(), + norm(e.readYn(), "Y"), norm(e.writeYn(), "N")); + } + } + } + + private static String norm(String v, String def) { + return "Y".equalsIgnoreCase(v) ? "Y" : ("N".equalsIgnoreCase(v) ? "N" : def); + } + + private static RoleMenuDto toDto(Map r) { + return new RoleMenuDto(str(r.get("menuId")), str(r.get("menuName")), str(r.get("parentId")), + intv(r.get("sortOrder")), bool(r.get("mapped")), str(r.get("readYn")), str(r.get("writeYn"))); + } + private static String str(Object o) { return o == null ? null : String.valueOf(o); } + private static Integer intv(Object o) { + if (o instanceof Number n) return n.intValue(); + return o == null ? 0 : Integer.parseInt(String.valueOf(o)); + } + private static boolean bool(Object o) { + if (o instanceof Boolean b) return b; + return o != null && Boolean.parseBoolean(String.valueOf(o)); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/syshealth/SystemHealthController.java b/src/backend/src/main/java/com/zioinfo/kintex/system/syshealth/SystemHealthController.java new file mode 100644 index 0000000..da79243 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/syshealth/SystemHealthController.java @@ -0,0 +1,27 @@ +package com.zioinfo.kintex.system.syshealth; + +import com.zioinfo.kintex.auth.KintexPrincipal; +import com.zioinfo.kintex.common.ApiResponse; +import com.zioinfo.kintex.system.SystemAccessGuard; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +/** 시스템관리 — 시스템 상태 대시보드 API. ADMIN 게이트(공개 /health 와 별개, 확장 지표). */ +@RestController +@RequestMapping("/api/admin/system-health") +public class SystemHealthController { + + private final SystemHealthService service; + private final SystemAccessGuard guard; + + public SystemHealthController(SystemHealthService service, SystemAccessGuard guard) { + this.service = service; + this.guard = guard; + } + + @GetMapping + public ApiResponse health(@AuthenticationPrincipal KintexPrincipal principal) { + guard.requireAdmin(principal); + return ApiResponse.ok(service.health()); + } +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/syshealth/SystemHealthDto.java b/src/backend/src/main/java/com/zioinfo/kintex/system/syshealth/SystemHealthDto.java new file mode 100644 index 0000000..ace9303 --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/syshealth/SystemHealthDto.java @@ -0,0 +1,29 @@ +package com.zioinfo.kintex.system.syshealth; + +/** + * 시스템 상태 요약(운영 대시보드). 민감정보(내부IP·스택트레이스) 미노출. + * + * @param db DB 연결 UP/DOWN + * @param redis Redis 연결 UP/DOWN + * @param worker 렌더 워커 큐 상태 UP/IDLE/DOWN(추정: 큐 접근 가능 여부) + * @param queueDepth 렌더 작업 큐 적재 수(측정 불가 시 -1) + * @param diskFreePct 디스크 여유 비율(%) + * @param diskFreeMb 디스크 여유 용량(MB) + * @param memUsedPct 힙 메모리 사용률(%) + * @param uptimeSec 가동 시간(초) + * @param version 애플리케이션 버전 + * @param time 서버 시각(ISO) + */ +public record SystemHealthDto( + String db, + String redis, + String worker, + long queueDepth, + long diskFreePct, + long diskFreeMb, + long memUsedPct, + long uptimeSec, + String version, + String time +) { +} diff --git a/src/backend/src/main/java/com/zioinfo/kintex/system/syshealth/SystemHealthService.java b/src/backend/src/main/java/com/zioinfo/kintex/system/syshealth/SystemHealthService.java new file mode 100644 index 0000000..73300cb --- /dev/null +++ b/src/backend/src/main/java/com/zioinfo/kintex/system/syshealth/SystemHealthService.java @@ -0,0 +1,114 @@ +package com.zioinfo.kintex.system.syshealth; + +import com.zioinfo.kintex.module.m5.RenderProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.lang.management.ManagementFactory; +import java.time.OffsetDateTime; + +/** + * 시스템 상태 집계(actuator 미도입, 의존성 0 커스텀) — ADMIN 전용. + * DB=경량 SELECT 1, Redis=ping, worker=렌더 큐 접근 가능 여부·적재량, 디스크/메모리=JVM 표준. + * 스택트레이스·내부IP 미노출. + */ +@Service +public class SystemHealthService { + + private static final Logger log = LoggerFactory.getLogger(SystemHealthService.class); + private static final String VERSION = "1.0.0"; + + private final JdbcTemplate jdbcTemplate; + private final StringRedisTemplate redis; + private final RenderProperties renderProps; + + public SystemHealthService(JdbcTemplate jdbcTemplate, StringRedisTemplate redis, + RenderProperties renderProps) { + this.jdbcTemplate = jdbcTemplate; + this.redis = redis; + this.renderProps = renderProps; + } + + public SystemHealthDto health() { + boolean redisUp = redisUp(); + long depth = redisUp ? queueDepth() : -1L; + return new SystemHealthDto( + dbStatus(), + redisUp ? "UP" : "DOWN", + workerStatus(redisUp, depth), + depth, + diskFreePct(), + diskFreeMb(), + memUsedPct(), + uptimeSec(), + VERSION, + OffsetDateTime.now().toString()); + } + + private String dbStatus() { + try { + jdbcTemplate.queryForObject("SELECT 1", Integer.class); + return "UP"; + } catch (Exception e) { + log.warn("[HEALTH] DB DOWN: {}", e.getClass().getSimpleName()); + return "DOWN"; + } + } + + private boolean redisUp() { + org.springframework.data.redis.connection.RedisConnectionFactory factory = redis.getConnectionFactory(); + if (factory == null) { + return false; + } + try (org.springframework.data.redis.connection.RedisConnection conn = factory.getConnection()) { + String pong = conn.ping(); + return pong != null; + } catch (Exception e) { + log.warn("[HEALTH] Redis DOWN: {}", e.getClass().getSimpleName()); + return false; + } + } + + private long queueDepth() { + try { + Long size = redis.opsForList().size(renderProps.getQueueKey()); + return size == null ? 0L : size; + } catch (Exception e) { + return -1L; + } + } + + /** 워커 상태(추정): Redis 접근 불가=DOWN, 큐 비어있음=IDLE, 적재 있음=UP. */ + private String workerStatus(boolean redisUp, long depth) { + if (!redisUp || depth < 0) { + return "DOWN"; + } + return depth == 0 ? "IDLE" : "UP"; + } + + private long diskFreePct() { + File root = new File("."); + long total = root.getTotalSpace(); + long usable = root.getUsableSpace(); + return total <= 0 ? -1 : Math.round(usable * 100.0 / total); + } + + private long diskFreeMb() { + return new File(".").getUsableSpace() / (1024 * 1024); + } + + private long memUsedPct() { + Runtime rt = Runtime.getRuntime(); + long used = rt.totalMemory() - rt.freeMemory(); + long max = rt.maxMemory(); + return max <= 0 ? -1 : Math.round(used * 100.0 / max); + } + + private long uptimeSec() { + return ManagementFactory.getRuntimeMXBean().getUptime() / 1000; + } +} diff --git a/src/backend/src/main/resources/application.yml b/src/backend/src/main/resources/application.yml index 572d3d8..baf91b8 100644 --- a/src/backend/src/main/resources/application.yml +++ b/src/backend/src/main/resources/application.yml @@ -34,6 +34,19 @@ spring: host: ${REDIS_HOST:localhost} port: ${REDIS_PORT:6379} password: ${REDIS_PASSWORD:} + # 메일(자체 Postfix SMTP — mail.zioinfo.co.kr, GUARDiA 운영). 자격증명은 env 주입만(하드코딩 금지). + # 실 발송은 MAIL_ENABLED=true 일 때만. 미주입 시 인앱/스킵 로그만 남긴다(정직 로그). + mail: + host: ${SMTP_HOST:mail.zioinfo.co.kr} + port: ${SMTP_PORT:587} + username: ${SMTP_USER:} + password: ${SMTP_PASSWORD:} + properties: + mail.smtp.auth: ${SMTP_AUTH:true} + mail.smtp.starttls.enable: ${SMTP_STARTTLS:true} + mail.smtp.connectiontimeout: 8000 + mail.smtp.timeout: 8000 + mail.smtp.writetimeout: 8000 # Flyway — 순번 DDL/시드가 스키마의 권위(sql.init 미사용, 후행 테이블 미적용 함정 회피). flyway: enabled: ${FLYWAY_ENABLED:true} @@ -69,6 +82,12 @@ kintex: email: ${ADMIN_EMAIL:} password: ${ADMIN_PASSWORD:} display-name: ${ADMIN_DISPLAY_NAME:시스템관리자} + # 메일 발송 채널(옥션 개설 통지·EDM·비밀번호 재설정). enabled=false면 인앱/스킵 로그만(실 전송 없음). + mail: + enabled: ${MAIL_ENABLED:false} + from: ${MAIL_FROM:no-reply@kintex.zioinfo.co.kr} + # 재설정 링크의 프론트 베이스 URL — 링크는 코드 안내용(프론트 reset 흐름은 이메일+코드 입력). + web-base-url: ${WEB_BASE_URL:https://kintex.zioinfo.co.kr} rules: # 버전 관리되는 룰셋 데이터(규정·요율) — 코드가 아닌 데이터로 유지(킨텍스 규정 개정 대응) compliance-ruleset: classpath:rulesets/compliance-v1.json diff --git a/src/backend/src/main/resources/db/migration/V36__mail_log.sql b/src/backend/src/main/resources/db/migration/V36__mail_log.sql new file mode 100644 index 0000000..c16ffac --- /dev/null +++ b/src/backend/src/main/resources/db/migration/V36__mail_log.sql @@ -0,0 +1,20 @@ +-- V36: 메일 발송 이력(mail_log) — 자체 Postfix SMTP 채널(옥션 개설 통지·EDM·비밀번호 재설정). +-- 소유자 승인(2026-07-12): 자체 인프라 SMTP(mail.zioinfo.co.kr) 연결. 외부 SaaS 아님. +-- 불변: V1~V35 파일 불변. 본 마이그레이션은 순증(additive)·멱등만 수행한다. +-- 보안 불변(§0-3): 본문·SMTP 자격증명은 저장하지 않는다. 수신자는 마스킹(kim***@do.com)만 저장. +-- 테넌트 표준(V31): tenant_id DEFAULT 'KINTEX' + 복합 PK (tenant_id, id). + +CREATE TABLE IF NOT EXISTS mail_log ( + tenant_id varchar(40) NOT NULL DEFAULT 'KINTEX', + id varchar(40) NOT NULL, + category varchar(30) NOT NULL, -- AUCTION_OPEN|EDM|PASSWORD_RESET + ref_id varchar(40), -- 연관 대상(auction_id·campaign_id 등) + subject varchar(300) NOT NULL, -- 제목만(본문 미저장) + recipient_masked varchar(200) NOT NULL, -- 마스킹 수신자(원문 저장 금지) + status varchar(20) NOT NULL DEFAULT 'sent', -- sent|failed|skipped + detail varchar(300), -- 요약(실패 사유 요약 — 스택트레이스 금지) + created_at timestamptz NOT NULL DEFAULT now(), + PRIMARY KEY (tenant_id, id) +); +CREATE INDEX IF NOT EXISTS idx_mail_log_category ON mail_log (tenant_id, category, created_at DESC); +CREATE INDEX IF NOT EXISTS idx_mail_log_ref ON mail_log (tenant_id, ref_id); diff --git a/src/backend/src/main/resources/db/migration/V37__system_basics.sql b/src/backend/src/main/resources/db/migration/V37__system_basics.sql new file mode 100644 index 0000000..f3cbda4 --- /dev/null +++ b/src/backend/src/main/resources/db/migration/V37__system_basics.sql @@ -0,0 +1,171 @@ +-- V37 시스템관리 기본기 이식 1차 (WISE/UIWS system.* 이식 — 소유자 지적 2026-07-12) +-- 목표: 조직(부서/회사)·프로그램·역할-메뉴 매핑·인증정책·로그인이력·오류로그 기본 테이블. +-- 불변: V1~V36 파일 불변. 본 마이그레이션은 순증(additive)·멱등만 수행한다(단일 트랜잭션). +-- 테넌트 표준(V31): 엔티티 테이블은 tenant_id DEFAULT 'KINTEX' + 복합 PK (tenant_id, id) 선두. +-- 전역 매핑/설정(role-menu 등 sys_role·sys_menu 참조)은 기존 sys_role_permission 규약과 정합(테넌트 미부여). +-- 보안 불변(§0-3): 비밀번호·시크릿·스택트레이스 미저장. 이메일/IP는 마스킹만 저장. + +-- ============================================================================ +-- 1) 조직 — 부서(dept) 트리 · 회사(company) +-- ============================================================================ +CREATE TABLE IF NOT EXISTS dept ( + tenant_id varchar(40) NOT NULL DEFAULT 'KINTEX', + id varchar(40) NOT NULL, + dept_name varchar(120) NOT NULL, + parent_id varchar(40), + sort_order integer NOT NULL DEFAULT 0, + use_yn char(1) NOT NULL DEFAULT 'Y', + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now(), + PRIMARY KEY (tenant_id, id) +); +CREATE INDEX IF NOT EXISTS idx_dept_parent ON dept (tenant_id, parent_id, sort_order); + +CREATE TABLE IF NOT EXISTS company ( + tenant_id varchar(40) NOT NULL DEFAULT 'KINTEX', + id varchar(40) NOT NULL, + company_name varchar(200) NOT NULL, + biz_no varchar(40), + ceo_name varchar(120), + biz_type varchar(120), + contact_name varchar(120), + contact_tel varchar(60), -- 저장은 원문, 응답은 마스킹(코드 계층) + address varchar(400), + partner_type varchar(40), -- 공통코드(PARTNER_TYPE) 값 + use_yn char(1) NOT NULL DEFAULT 'Y', + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now(), + PRIMARY KEY (tenant_id, id) +); +CREATE INDEX IF NOT EXISTS idx_company_name ON company (tenant_id, company_name); + +-- ============================================================================ +-- 2) 프로그램(화면) 등록부 — 메뉴와 연결되는 라우트/화면 마스터 +-- ============================================================================ +CREATE TABLE IF NOT EXISTS sys_program ( + tenant_id varchar(40) NOT NULL DEFAULT 'KINTEX', + id varchar(40) NOT NULL, + program_name varchar(160) NOT NULL, + program_type varchar(20) NOT NULL DEFAULT 'SCREEN', -- SCREEN|POPUP|LINK + program_url varchar(300), -- 라우트 경로(/admin/users 등) + category varchar(80), + use_yn char(1) NOT NULL DEFAULT 'Y', + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now(), + PRIMARY KEY (tenant_id, id) +); +CREATE INDEX IF NOT EXISTS idx_sys_program_cat ON sys_program (tenant_id, category, program_name); + +-- ============================================================================ +-- 3) 역할-메뉴 매핑 — 역할별 메뉴 접근(read/write). sys_role·sys_menu 참조(전역 규약). +-- ============================================================================ +CREATE TABLE IF NOT EXISTS sys_role_menu ( + role_code varchar(20) NOT NULL REFERENCES sys_role(role_code) ON DELETE CASCADE, + menu_id varchar(40) NOT NULL REFERENCES sys_menu(id) ON DELETE CASCADE, + read_yn char(1) NOT NULL DEFAULT 'Y', + write_yn char(1) NOT NULL DEFAULT 'N', + PRIMARY KEY (role_code, menu_id) +); +CREATE INDEX IF NOT EXISTS idx_sys_role_menu_role ON sys_role_menu (role_code); + +-- ============================================================================ +-- 4) 인증 정책 — 비밀번호 정책·로그인 잠금 임계(테넌트 싱글턴 1행) +-- 기존 LoginAttemptService/sys_setting(login.*) 값을 정책화(코드 계층은 sys_setting 유지·본 표는 관리 조회). +-- ============================================================================ +CREATE TABLE IF NOT EXISTS sys_auth_policy ( + tenant_id varchar(40) NOT NULL DEFAULT 'KINTEX', + pw_min_length integer NOT NULL DEFAULT 8, + pw_require_upper char(1) NOT NULL DEFAULT 'N', + pw_require_number char(1) NOT NULL DEFAULT 'Y', + pw_require_special char(1) NOT NULL DEFAULT 'N', + pw_expire_days integer NOT NULL DEFAULT 0, -- 0 = 만료 없음 + login_max_fail integer NOT NULL DEFAULT 5, + lock_minutes integer NOT NULL DEFAULT 15, + session_timeout_min integer NOT NULL DEFAULT 120, + updated_at timestamptz NOT NULL DEFAULT now(), + updated_by varchar(40), + PRIMARY KEY (tenant_id) +); +INSERT INTO sys_auth_policy (tenant_id) VALUES ('KINTEX') +ON CONFLICT (tenant_id) DO NOTHING; + +-- ============================================================================ +-- 5) 로그인 이력(신설) — 성공/실패. 이메일/IP 마스킹만 저장(원문 금지). +-- ============================================================================ +CREATE TABLE IF NOT EXISTS login_history ( + tenant_id varchar(40) NOT NULL DEFAULT 'KINTEX', + id bigserial NOT NULL, + user_id varchar(40), + email_masked varchar(200), -- kim***@do.com + result varchar(20) NOT NULL DEFAULT 'SUCCESS', -- SUCCESS|FAIL|LOCKED + fail_reason varchar(60), -- BAD_CREDENTIAL|LOCKED (요약) + ip_masked varchar(60), -- 203.0.113.* (원문 금지) + user_agent varchar(300), + created_at timestamptz NOT NULL DEFAULT now(), + PRIMARY KEY (tenant_id, id) +); +CREATE INDEX IF NOT EXISTS idx_login_history_created ON login_history (tenant_id, created_at DESC); +CREATE INDEX IF NOT EXISTS idx_login_history_user ON login_history (tenant_id, user_id); +CREATE INDEX IF NOT EXISTS idx_login_history_result ON login_history (tenant_id, result, created_at DESC); + +-- ============================================================================ +-- 6) 오류 로그(신설) — GlobalExceptionHandler 500 요약 1줄(스택트레이스 미저장). +-- ============================================================================ +CREATE TABLE IF NOT EXISTS error_log ( + tenant_id varchar(40) NOT NULL DEFAULT 'KINTEX', + id bigserial NOT NULL, + error_code varchar(60), -- INTERNAL 등 + summary varchar(500), -- 예외 클래스 + 요약(민감정보·스택 제외) + path varchar(300), + method varchar(10), + actor_id varchar(40), + created_at timestamptz NOT NULL DEFAULT now(), + PRIMARY KEY (tenant_id, id) +); +CREATE INDEX IF NOT EXISTS idx_error_log_created ON error_log (tenant_id, created_at DESC); +CREATE INDEX IF NOT EXISTS idx_error_log_code ON error_log (tenant_id, error_code, created_at DESC); + +-- ============================================================================ +-- 7) 공통코드 순증 — PARTNER_TYPE(회사 분류) +-- ============================================================================ +INSERT INTO common_code_group (grp_code, grp_name, description, sort_order) VALUES + ('PARTNER_TYPE', '거래처 분류', 'company 이식', 20) +ON CONFLICT (grp_code) DO UPDATE SET grp_name = EXCLUDED.grp_name, description = EXCLUDED.description; +INSERT INTO common_code (grp_code, code, code_name, sort_order) VALUES + ('PARTNER_TYPE','CONTRACTOR','장치업체',1), + ('PARTNER_TYPE','SUPPLIER','공급업체',2), + ('PARTNER_TYPE','AGENCY','대행사',3), + ('PARTNER_TYPE','ETC','기타',4) +ON CONFLICT (grp_code, code) DO UPDATE SET code_name = EXCLUDED.code_name, sort_order = EXCLUDED.sort_order; + +-- ============================================================================ +-- 8) 시스템관리 메뉴 순증 — 신규 화면(조직·프로그램·역할메뉴·인증정책·로그인이력·오류로그·시스템상태·메일/알림) +-- ============================================================================ +INSERT INTO sys_menu (id, parent_id, menu_name, menu_path, icon, sort_order, required_role) VALUES + ('m-sys-dept', 'm-sys', '조직 관리', '/admin/depts', 'sitemap', 10, 'ADMIN'), + ('m-sys-comp', 'm-sys', '회사 관리', '/admin/companies', 'building', 11, 'ADMIN'), + ('m-sys-prog', 'm-sys', '프로그램 관리','/admin/programs', 'window', 12, 'ADMIN'), + ('m-sys-rmenu', 'm-sys', '역할-메뉴', '/admin/role-menus', 'grid', 13, 'ADMIN'), + ('m-sys-authp', 'm-sys', '인증 정책', '/admin/auth-policy', 'lock', 14, 'ADMIN'), + ('m-sys-login', 'm-sys', '로그인 이력', '/admin/login-history','log-in', 15, 'ADMIN'), + ('m-sys-errlog', 'm-sys', '오류 로그', '/admin/error-log', 'alert', 16, 'ADMIN'), + ('m-sys-health', 'm-sys', '시스템 상태', '/admin/system-health','activity', 17, 'ADMIN'), + ('m-sys-mail', 'm-sys', '메일 설정', '/admin/mail-config', 'mail', 18, 'ADMIN'), + ('m-sys-notify', 'm-sys', '알림 설정', '/admin/notify-config','bell', 19, 'ADMIN') +ON CONFLICT (id) DO UPDATE SET menu_name = EXCLUDED.menu_name, menu_path = EXCLUDED.menu_path, + icon = EXCLUDED.icon, sort_order = EXCLUDED.sort_order, required_role = EXCLUDED.required_role; + +-- ============================================================================ +-- 9) 메일/알림 설정 기본값(sys_setting) — mail.* / notify.* (시크릿은 secret_yn='Y') +-- ============================================================================ +INSERT INTO sys_setting (setting_key, setting_value, value_type, description, secret_yn) VALUES + ('mail.enabled', 'true', 'BOOL', '메일 발송 사용', 'N'), + ('mail.host', 'mail.zioinfo.co.kr', 'STRING', 'SMTP 호스트', 'N'), + ('mail.port', '587', 'INT', 'SMTP 포트', 'N'), + ('mail.fromAddress', 'noreply@kintex.co.kr', 'STRING', '발신 주소', 'N'), + ('mail.fromName', 'KINTEX', 'STRING', '발신자 표기', 'N'), + ('mail.password', '', 'STRING', 'SMTP 비밀번호(env 주입 권장)', 'Y'), + ('notify.email.enabled', 'true', 'BOOL', '이메일 알림 채널', 'N'), + ('notify.inapp.enabled', 'true', 'BOOL', '인앱 알림 채널', 'N'), + ('notify.webhook.enabled', 'false', 'BOOL', '웹훅 알림 채널', 'N') +ON CONFLICT (setting_key) DO NOTHING; diff --git a/src/backend/src/main/resources/db/migration/V38__demo_seed_full.sql b/src/backend/src/main/resources/db/migration/V38__demo_seed_full.sql new file mode 100644 index 0000000..a4256bf --- /dev/null +++ b/src/backend/src/main/resources/db/migration/V38__demo_seed_full.sql @@ -0,0 +1,546 @@ +-- ============================================================================ +-- V38 마스터 + 데모 폐루프 데이터 전면 시드 (킨텍스 리뉴얼 Phase 2) +-- 담당: kintex-testdata-dev · 작성: 2026-07-12 +-- ---------------------------------------------------------------------------- +-- 원칙(불변): +-- • V1~V37 파일 불변. 본 파일은 순증(additive)만 수행하며 전부 순수 INSERT ... ON CONFLICT DO NOTHING. +-- (기존 시드/실데이터 UPDATE·DELETE 절대 금지 — 재실행·재배포 안전.) +-- • 테넌트 표준 = 'KINTEX'(대문자, V31 정규화). tenant_id 보유 테이블만 명시 세팅. +-- • 폐루프 축 = 기존 행사 e-2026-smf(2026 스마트팩토리 코리아, 개장 2026-08-11). +-- • PII(이름/전화/이메일)는 전부 가짜 더미(@kintex.test · 010-0000-xxxx 계열). 실존 인물 금지. +-- • 마감/할 일 활성화 날짜는 now()/CURRENT_DATE 상대값(배포 시점 기준으로 항상 유효). +-- 홈 할 일(HomeMapper) 활성화 대상: +-- 결재 대기(approval_line.CURRENT), 서류 D-3(required_document due=CURRENT_DATE+3), +-- 옥션 낙찰 선정(마감 경과+낙찰 미확정 AUC-2026-0511), 응찰 마감 임박(AUC-2026-0102 D-2), +-- 미수 청구(invoice pending/overdue), 오늘 체크인(visitor_registration.checkin_at::date=today). +-- ============================================================================ + + +-- ============================================================================ +-- 1. 마스터 데이터 +-- ============================================================================ + +-- 1-1) 공통코드 — 실사용 그룹(부스 타입·서류 상태·옥션 카테고리·업종) -------------- +INSERT INTO common_code_group (grp_code, grp_name, description, sort_order) VALUES + ('BOOTH_TYPE', '부스 타입', 'booth.booth_type — assembled|independent|corner|island', 30), + ('DOC_STATUS', '서류 상태', 'required_document.status', 31), + ('AUCTION_CATEGORY', '옥션 카테고리', 'auction.category — 공사/장치 발주 분류', 32), + ('INDUSTRY', '업종', '참가업체/리드 업종 분류', 33), + ('INVOICE_STATUS', '청구 상태', 'invoice.status', 34), + ('BOOTH_SALE_STATUS','부스 판매상태', 'booth_sale.status', 35) +ON CONFLICT (grp_code) DO NOTHING; + +INSERT INTO common_code (grp_code, code, code_name, sort_order) VALUES + ('BOOTH_TYPE','assembled','조립부스',1), + ('BOOTH_TYPE','independent','독립부스',2), + ('BOOTH_TYPE','corner','코너부스',3), + ('BOOTH_TYPE','island','아일랜드부스',4), + ('DOC_STATUS','pending','대기',1), + ('DOC_STATUS','draft','작성중',2), + ('DOC_STATUS','submitted','제출',3), + ('DOC_STATUS','approved','승인',4), + ('DOC_STATUS','rejected','반려',5), + ('AUCTION_CATEGORY','전시디자인설치','전시디자인설치',1), + ('AUCTION_CATEGORY','구조물 임대','구조물 임대',2), + ('AUCTION_CATEGORY','전기/조명','전기/조명',3), + ('AUCTION_CATEGORY','영상/음향','영상/음향',4), + ('AUCTION_CATEGORY','네트워크','네트워크',5), + ('INDUSTRY','MFG','제조/자동화',1), + ('INDUSTRY','ROBOT','로봇',2), + ('INDUSTRY','ELEC','전기/전자',3), + ('INDUSTRY','LOGI','물류/유통',4), + ('INDUSTRY','ICT','ICT/소프트웨어',5), + ('INDUSTRY','BIO','바이오/헬스',6), + ('INDUSTRY','ETC','기타',7), + ('INVOICE_STATUS','pending','미발행',1), + ('INVOICE_STATUS','invoiced','발행',2), + ('INVOICE_STATUS','paid','완납',3), + ('INVOICE_STATUS','overdue','연체',4), + ('INVOICE_STATUS','cancelled','취소',5), + ('BOOTH_SALE_STATUS','available','판매가능',1), + ('BOOTH_SALE_STATUS','held','선점',2), + ('BOOTH_SALE_STATUS','sold','판매완료',3), + ('BOOTH_SALE_STATUS','blocked','판매불가',4) +ON CONFLICT (grp_code, code) DO NOTHING; + +-- 1-2) 프로그램 등록부(sys_program) — App.tsx 라우트 스캔·화면 등록 ----------------- +INSERT INTO sys_program (tenant_id, id, program_name, program_type, program_url, category) VALUES + ('KINTEX','pg-home','메인 홈','SCREEN','/home','공통'), + ('KINTEX','pg-login','로그인','SCREEN','/login','인증'), + ('KINTEX','pg-otp','OTP 설정','SCREEN','/otp-setup','인증'), + ('KINTEX','pg-dashboard','행사 대시보드','SCREEN','/events/:eventId/dashboard','부스코어'), + ('KINTEX','pg-booth-home','부스 홈','SCREEN','/events/:eventId/booths/:boothId/home','부스코어'), + ('KINTEX','pg-layout','홀 배치 에디터','SCREEN','/events/:eventId/halls/:hallId/layout','부스코어'), + ('KINTEX','pg-comparison','배치안 비교','SCREEN','/events/:eventId/halls/:hallId/comparison','부스코어'), + ('KINTEX','pg-design','부스 설계','SCREEN','/events/:eventId/booths/:boothId/design','부스코어'), + ('KINTEX','pg-utility','유틸리티','SCREEN','/events/:eventId/booths/:boothId/utility','부스코어'), + ('KINTEX','pg-utility-order','유틸리티 신청','SCREEN','/events/:eventId/booths/:boothId/utility/order','부스코어'), + ('KINTEX','pg-compliance','규정 검토','SCREEN','/events/:eventId/booths/:boothId/compliance','부스코어'), + ('KINTEX','pg-review','도면 검수','SCREEN','/events/:eventId/halls/:hallId/booths/:booth/review','부스코어'), + ('KINTEX','pg-gallery','AI 갤러리','SCREEN','/events/:eventId/booths/:boothId/gallery','부스코어'), + ('KINTEX','pg-booth-sales','부스 판매','SCREEN','/booth-sales','부스코어'), + ('KINTEX','pg-halls','전시장/홀','SCREEN','/halls','부스코어'), + ('KINTEX','pg-analytics','경영분석/BI','SCREEN','/analytics','도메인'), + ('KINTEX','pg-ops','운영 관제','SCREEN','/ops/operations','도메인'), + ('KINTEX','pg-docs','신고서류','SCREEN','/docs','도메인'), + ('KINTEX','pg-docs-authoring','서류 작성','SCREEN','/docs/authoring','도메인'), + ('KINTEX','pg-logistics','물류/반입반출','SCREEN','/logistics','도메인'), + ('KINTEX','pg-auctions','공사 옥션','SCREEN','/auctions','도메인'), + ('KINTEX','pg-auction-detail','옥션 상세','SCREEN','/auctions/:auctionId','도메인'), + ('KINTEX','pg-auction-award','옥션 낙찰선정','SCREEN','/auctions/:auctionId/award','도메인'), + ('KINTEX','pg-contractor','공사업체 대시보드','SCREEN','/contractor/dashboard','도메인'), + ('KINTEX','pg-visitors','관람객 등록','SCREEN','/visitors','도메인'), + ('KINTEX','pg-checkin','현장 체크인','SCREEN','/visitors/checkin','도메인'), + ('KINTEX','pg-leads','리드 스코어링','SCREEN','/leads','도메인'), + ('KINTEX','pg-campaigns','EDM 캠페인','SCREEN','/campaigns','도메인'), + ('KINTEX','pg-sponsorship','스폰서십','SCREEN','/sponsorship','도메인'), + ('KINTEX','pg-cms','CMS','SCREEN','/cms','도메인'), + ('KINTEX','pg-cms-microsite','마이크로사이트','SCREEN','/cms/microsite','도메인'), + ('KINTEX','pg-cms-i18n','다국어 관리','SCREEN','/cms/i18n','도메인'), + ('KINTEX','pg-settlement','정산/청구','SCREEN','/settlement','도메인'), + ('KINTEX','pg-work-approval','전자결재','SCREEN','/work/approval','공통업무'), + ('KINTEX','pg-work-worklog','업무일지','SCREEN','/work/worklog','공통업무'), + ('KINTEX','pg-work-schedule','일정','SCREEN','/work/schedule','공통업무'), + ('KINTEX','pg-work-message','쪽지','SCREEN','/work/message','공통업무'), + ('KINTEX','pg-work-notice','공지','SCREEN','/work/notice','공통업무'), + ('KINTEX','pg-work-opinion','의견','SCREEN','/work/opinion','공통업무'), + ('KINTEX','pg-work-meeting','회의','SCREEN','/work/meeting','공통업무'), + ('KINTEX','pg-work-report','보고서','SCREEN','/work/report','공통업무'), + ('KINTEX','pg-work-search','통합검색','SCREEN','/work/search','공통업무'), + ('KINTEX','pg-notifications','알림','SCREEN','/notifications','공통업무'), + ('KINTEX','pg-me','내 정보','SCREEN','/me','공통업무'), + ('KINTEX','pg-admin','관리 대시보드','SCREEN','/admin','시스템관리'), + ('KINTEX','pg-admin-users','사용자 관리','SCREEN','/admin/users','시스템관리'), + ('KINTEX','pg-admin-roles','역할/권한','SCREEN','/admin/roles','시스템관리'), + ('KINTEX','pg-admin-codes','공통코드','SCREEN','/admin/codes','시스템관리'), + ('KINTEX','pg-admin-menus','메뉴 관리','SCREEN','/admin/menus','시스템관리'), + ('KINTEX','pg-admin-depts','조직 관리','SCREEN','/admin/depts','시스템관리'), + ('KINTEX','pg-admin-companies','회사 관리','SCREEN','/admin/companies','시스템관리'), + ('KINTEX','pg-admin-programs','프로그램 관리','SCREEN','/admin/programs','시스템관리'), + ('KINTEX','pg-admin-role-menus','역할-메뉴','SCREEN','/admin/role-menus','시스템관리'), + ('KINTEX','pg-admin-auth-policy','인증 정책','SCREEN','/admin/auth-policy','시스템관리'), + ('KINTEX','pg-admin-login-history','로그인 이력','SCREEN','/admin/login-history','시스템관리'), + ('KINTEX','pg-admin-error-log','오류 로그','SCREEN','/admin/error-log','시스템관리'), + ('KINTEX','pg-admin-system-health','시스템 상태','SCREEN','/admin/system-health','시스템관리'), + ('KINTEX','pg-admin-settings','시스템 설정','SCREEN','/admin/settings','시스템관리'), + ('KINTEX','pg-admin-audit','감사로그','SCREEN','/admin/audit','시스템관리'), + ('KINTEX','pg-admin-rulesets','규정/요율 룰셋','SCREEN','/admin/masterdata/rulesets','시스템관리'), + ('KINTEX','pg-admin-tenants','테넌트 관리','SCREEN','/admin/tenants','시스템관리'), + ('KINTEX','pg-admin-login-slides','로그인 슬라이드','SCREEN','/admin/login-slides','시스템관리'), + ('KINTEX','pg-admin-mail-config','메일 설정','SCREEN','/admin/mail-config','시스템관리'), + ('KINTEX','pg-admin-notify-config','알림 설정','SCREEN','/admin/notify-config','시스템관리'), + ('KINTEX','pg-app-qr','앱 QR 배포','SCREEN','/app-qr','시스템관리'), + ('KINTEX','pg-public','공개 홈','SCREEN','/public','공개사이트'), + ('KINTEX','pg-public-event','공개 행사','SCREEN','/public/events/:eventId','공개사이트'), + ('KINTEX','pg-public-floorplan','공개 평면도','SCREEN','/public/events/:eventId/floorplan','공개사이트'), + ('KINTEX','pg-public-register','관람객 사전등록','SCREEN','/public/events/:eventId/register','공개사이트'), + ('KINTEX','pg-public-exhibitor','공개 참가업체','SCREEN','/public/exhibitors/:exhibitorId','공개사이트'), + ('KINTEX','pg-public-inquiry','참가문의','SCREEN','/public/exhibit-inquiry','공개사이트'), + ('KINTEX','pg-ticket-purchase','입장권 구매','SCREEN','/tickets/:eventId/purchase','공개사이트'), + ('KINTEX','pg-ticket-lookup','입장권 조회','SCREEN','/tickets/lookup','공개사이트'), + ('KINTEX','pg-m-checklist','현장 체크리스트(모바일)','SCREEN','/m/booths/:boothId/checklist','모바일'), + ('KINTEX','pg-m-inspection','현장 점검(모바일)','SCREEN','/m/booths/:boothId/inspection','모바일') +ON CONFLICT (tenant_id, id) DO NOTHING; + +-- 1-3) 부서 트리(dept) — 3레벨 -------------------------------------------------- +INSERT INTO dept (tenant_id, id, dept_name, parent_id, sort_order) VALUES + ('KINTEX','d-exhib', '전시사업본부', NULL, 1), + ('KINTEX','d-hall', '홀운영팀', 'd-exhib', 1), + ('KINTEX','d-hall-c1', '제1전시장파트', 'd-hall', 1), + ('KINTEX','d-hall-c2', '제2전시장파트', 'd-hall', 2), + ('KINTEX','d-sales', '전시영업팀', 'd-exhib', 2), + ('KINTEX','d-sales-dom','국내영업파트', 'd-sales', 1), + ('KINTEX','d-sales-glo','해외영업파트', 'd-sales', 2), + ('KINTEX','d-mkt', '마케팅팀', 'd-exhib', 3), + ('KINTEX','d-mgmt', '경영지원본부', NULL, 2), + ('KINTEX','d-fin', '재무회계팀', 'd-mgmt', 1), + ('KINTEX','d-fin-set', '정산파트', 'd-fin', 1), + ('KINTEX','d-hr', '인사총무팀', 'd-mgmt', 2), + ('KINTEX','d-it', '정보시스템본부', NULL, 3), + ('KINTEX','d-it-ops', '시스템운영팀', 'd-it', 1), + ('KINTEX','d-it-dev', '서비스개발팀', 'd-it', 2) +ON CONFLICT (tenant_id, id) DO NOTHING; + +-- 1-4) 회사(company) — 공사업체 2건 순증(V6 co-0001~4 포함 총 6) + 참가업체 10건 ----- +-- company 는 tenant_id 컬럼 없음(V2 스키마). UNIQUE(registration_no) 멱등 키. +INSERT INTO company (id, registration_no, name, category, region, registered, phone) VALUES + -- 공사(장치)업체 순증 2 (registered=true) + ('co-0005', '555-55-55555', '(주)미디어라이트', '영상/음향', '서울', true, '02-0000-5501'), + ('co-0006', '666-66-66666', '넷워크시스템즈', '네트워크', '경기', true, '031-000-6601'), + -- 참가업체 10 (전시 참가사 — 등록업체 DB 등재) + ('co-ex-01', '301-81-10001', '(주)스마트오토메이션', '제조/자동화', '경기', true, '031-000-1001'), + ('co-ex-02', '302-81-10002', '델타로보틱스', '로봇', '서울', true, '02-0000-1002'), + ('co-ex-03', '303-81-10003', '한국센서테크', '전기/전자', '인천', true, '032-000-1003'), + ('co-ex-04', '304-81-10004', '비전인더스트리', '제조/자동화', '경기', true, '031-000-1004'), + ('co-ex-05', '305-81-10005', '(주)테크솔루션', 'ICT/소프트웨어','서울',true, '02-0000-1005'), + ('co-ex-06', '306-81-10006', '넥스트이노베이션', 'ICT/소프트웨어','경기',true, '031-000-1006'), + ('co-ex-07', '307-81-10007', '글로벌테크', '물류/유통', '부산', true, '051-000-1007'), + ('co-ex-08', '308-81-10008', '미래제조연구소', '제조/자동화', '대전', true, '042-000-1008'), + ('co-ex-09', '309-81-10009', '두산로보틱스데모', '로봇', '경기', true, '031-000-1009'), + ('co-ex-10', '310-81-10010', '바이오헬스랩', '바이오/헬스', '서울', true, '02-0000-1010') +ON CONFLICT (registration_no) DO NOTHING; + +-- 공사업체 평판(company_reputation) — 순증 2건(V16 co-0001~4 포함 총 6) ------------ +INSERT INTO company_reputation (company_id, rating, jobs_done, claim_rate) VALUES + ('co-0005', 4.5, 9, 1.0), + ('co-0006', 4.3, 7, 1.8) +ON CONFLICT (company_id) DO NOTHING; + +-- 1-5) 요율 부족분 순증(master_data RATE — ON CONFLICT DO NOTHING) ----------------- +INSERT INTO master_data (category, code, name, value_json, ruleset_version) VALUES + ('RATE', 'independentBoothPerM2', '독립부스 임대 요율(원/㎡)', '2420'::jsonb, 'rates-v1.0'), + ('RATE', 'cornerPremiumPercent', '코너 가산율(%)', '10'::jsonb, 'rates-v1.0'), + ('RATE', 'lateApplicationPercent','마감 후 신청 가산율(%)', '20'::jsonb, 'rates-v1.0'), + ('UTILITY_FEE', 'network.wifiAp', '전용 WiFi AP(원)', '250000'::jsonb,'rates-v1.0'), + ('UTILITY_FEE', 'power.night24h', '24시간 전원 상시공급(원/kW)','82500'::jsonb,'rates-v1.0') +ON CONFLICT (category, code) DO NOTHING; + + +-- ============================================================================ +-- 2. 데모 계정 4 (app_user) + 행사 멤버십(event_member) +-- 비밀번호 규칙: Kintex!Demo1 · BCrypt($2a$10) · otp_enabled=false(데모 편의) +-- ============================================================================ +INSERT INTO app_user (tenant_id, id, email, display_name, password_hash, hall_manager, + role_code, status, verify_method, otp_enabled, dept_id, company_name) VALUES + ('KINTEX','demo-organizer','demo-organizer@kintex.test','데모 주최자(홍길동)', + '$2a$10$15dUJ7rlPO7kwgC/fgCUFuOK7Q0yS5lC4LTedszf1vn/R7CsShZ2y', false, + 'USER','ACTIVE','EMAIL', false, 'd-hall', 'KINTEX 전시사업본부'), + ('KINTEX','demo-exhibitor','demo-exhibitor@kintex.test','데모 참가업체(김참가)', + '$2a$10$aaUiIhPWfAMJ/AIfpZYBSurTRwnCYIY1R9mmmgpZyGVTMxXIyxlsC', false, + 'USER','ACTIVE','EMAIL', false, NULL, '(주)스마트오토메이션'), + ('KINTEX','demo-contractor','demo-contractor@kintex.test','데모 공사업체(이시공)', + '$2a$10$hFPyMTvnOYQwfHcktl9Kuu0W2/Mrl//IiSjS83wOmBd22enBDRj5G', false, + 'USER','ACTIVE','EMAIL', false, NULL, '(주)한빛부스디자인'), + ('KINTEX','demo-visitor','demo-visitor@kintex.test','데모 관람객(박관람)', + '$2a$10$UhVNjelRRZt3SpDCJfT.V.2pfHH9Lrme9KRteadUUJ1YhFwMvyH4K', false, + 'USER','ACTIVE','EMAIL', false, NULL, NULL) +ON CONFLICT (email) DO NOTHING; + +-- 행사 단위 RBAC — e-2026-smf. contractor 는 등록업체(co-0001) 연결 → 옥션 응찰 게이트 통과. +INSERT INTO event_member (id, event_id, user_id, role_code, booth_id, company_id) VALUES + ('em-demo-org', 'e-2026-smf', 'demo-organizer', 'ORGANIZER', NULL, NULL), + ('em-demo-exh', 'e-2026-smf', 'demo-exhibitor', 'EXHIBITOR', 'booth-smf-a102', NULL), + ('em-demo-con', 'e-2026-smf', 'demo-contractor', 'CONTRACTOR', NULL, 'co-0001') +ON CONFLICT (event_id, user_id, role_code) DO NOTHING; + + +-- ============================================================================ +-- 3. 부스 폐루프 — 홀 배정 + 데모 배치(layout) + 부스 12(POLYGON) + 판매 오버레이 +-- SRID 0 = 홀 로컬 평면(미터). 부스=6m×3m(18㎡) 4×3 그리드. +-- ============================================================================ +-- H1 홀 배정(V28 BOQ 레이아웃 정합) + 데모 부스용 배정은 기존 H7(primary) 사용. +INSERT INTO hall_assignment (id, event_id, hall_id, is_primary) VALUES + ('ha-2026-smf-h1', 'e-2026-smf', 'H1', false) +ON CONFLICT (event_id, hall_id) DO NOTHING; + +INSERT INTO layout (id, event_id, hall_id, version, name, status) VALUES + ('ly-smf-demo', 'e-2026-smf', 'H7', 1, 'SMF 데모 배치(판매)', 'confirmed') +ON CONFLICT (id) DO NOTHING; + +INSERT INTO booth (id, layout_id, booth_no, booth_type, geom, size_w_m, size_d_m, height_m, + floor_load_t_per_m2, assigned_company_name, premium) VALUES + ('booth-smf-b101','ly-smf-demo','B-101','independent',ST_GeomFromText('POLYGON((0 0,6 0,6 3,0 3,0 0))',0), 6,3,3.5,1.0,'(주)스마트오토메이션',true), + ('booth-smf-b102','ly-smf-demo','B-102','assembled', ST_GeomFromText('POLYGON((7 0,13 0,13 3,7 3,7 0))',0), 6,3,3.0,1.0,'델타로보틱스',false), + ('booth-smf-b103','ly-smf-demo','B-103','assembled', ST_GeomFromText('POLYGON((14 0,20 0,20 3,14 3,14 0))',0), 6,3,3.0,1.0,NULL,false), + ('booth-smf-b104','ly-smf-demo','B-104','corner', ST_GeomFromText('POLYGON((21 0,27 0,27 3,21 3,21 0))',0), 6,3,3.5,1.0,'한국센서테크',false), + ('booth-smf-b105','ly-smf-demo','B-105','assembled', ST_GeomFromText('POLYGON((0 4,6 4,6 7,0 7,0 4))',0), 6,3,3.0,1.0,NULL,false), + ('booth-smf-b106','ly-smf-demo','B-106','island', ST_GeomFromText('POLYGON((7 4,13 4,13 7,7 7,7 4))',0), 6,3,4.0,1.0,'비전인더스트리',true), + ('booth-smf-b107','ly-smf-demo','B-107','assembled', ST_GeomFromText('POLYGON((14 4,20 4,20 7,14 7,14 4))',0), 6,3,3.0,1.0,'(주)테크솔루션',false), + ('booth-smf-b108','ly-smf-demo','B-108','assembled', ST_GeomFromText('POLYGON((21 4,27 4,27 7,21 7,21 4))',0), 6,3,3.0,1.0,NULL,false), + ('booth-smf-b109','ly-smf-demo','B-109','independent',ST_GeomFromText('POLYGON((0 8,6 8,6 11,0 11,0 8))',0), 6,3,3.5,1.0,'넥스트이노베이션',false), + ('booth-smf-b110','ly-smf-demo','B-110','assembled', ST_GeomFromText('POLYGON((7 8,13 8,13 11,7 11,7 8))',0), 6,3,3.0,1.0,NULL,false), + ('booth-smf-b111','ly-smf-demo','B-111','corner', ST_GeomFromText('POLYGON((14 8,20 8,20 11,14 11,14 8))',0),6,3,3.5,1.0,'미래제조연구소',false), + ('booth-smf-b112','ly-smf-demo','B-112','assembled', ST_GeomFromText('POLYGON((21 8,27 8,27 11,21 11,21 8))',0),6,3,3.0,1.0,'바이오헬스랩',false) +ON CONFLICT (id) DO NOTHING; + +-- 판매 오버레이(booth_sale) — 상태 분포: sold 5 · available 4 · held 1 · blocked 2 ------- +INSERT INTO booth_sale (tenant_id, id, event_id, hall_id, booth_id, booth_no, status, unit_price, + area_m2, held_by, held_until, sold_to_company, sold_by, sold_at, + blocked_reason, created_by) VALUES + ('KINTEX','bs-smf-101','e-2026-smf','H7','booth-smf-b101','B-101','sold', 5445000,18,NULL,NULL,'(주)스마트오토메이션','demo-organizer',now()-interval '20 day',NULL,'system-seed'), + ('KINTEX','bs-smf-102','e-2026-smf','H7','booth-smf-b102','B-102','sold', 4356000,18,NULL,NULL,'델타로보틱스','demo-organizer',now()-interval '15 day',NULL,'system-seed'), + ('KINTEX','bs-smf-103','e-2026-smf','H7','booth-smf-b103','B-103','available', NULL, 18,NULL,NULL,NULL,NULL,NULL,NULL,'system-seed'), + ('KINTEX','bs-smf-104','e-2026-smf','H7','booth-smf-b104','B-104','sold', 4791600,18,NULL,NULL,'한국센서테크','demo-organizer',now()-interval '12 day',NULL,'system-seed'), + ('KINTEX','bs-smf-105','e-2026-smf','H7','booth-smf-b105','B-105','available', NULL, 18,NULL,NULL,NULL,NULL,NULL,NULL,'system-seed'), + ('KINTEX','bs-smf-106','e-2026-smf','H7','booth-smf-b106','B-106','sold', 6534000,18,NULL,NULL,'비전인더스트리','demo-organizer',now()-interval '8 day',NULL,'system-seed'), + ('KINTEX','bs-smf-107','e-2026-smf','H7','booth-smf-b107','B-107','sold', 4356000,18,NULL,NULL,'(주)테크솔루션','demo-organizer',now()-interval '5 day',NULL,'system-seed'), + ('KINTEX','bs-smf-108','e-2026-smf','H7','booth-smf-b108','B-108','held', NULL, 18,'demo-exhibitor',now()+interval '30 minute',NULL,NULL,NULL,NULL,'system-seed'), + ('KINTEX','bs-smf-109','e-2026-smf','H7','booth-smf-b109','B-109','available', NULL, 18,NULL,NULL,NULL,NULL,NULL,NULL,'system-seed'), + ('KINTEX','bs-smf-110','e-2026-smf','H7','booth-smf-b110','B-110','blocked', NULL, 18,NULL,NULL,NULL,NULL,NULL,'소방 통로 확보 구역','system-seed'), + ('KINTEX','bs-smf-111','e-2026-smf','H7','booth-smf-b111','B-111','available', NULL, 18,NULL,NULL,NULL,NULL,NULL,NULL,'system-seed'), + ('KINTEX','bs-smf-112','e-2026-smf','H7','booth-smf-b112','B-112','blocked', NULL, 18,NULL,NULL,NULL,NULL,NULL,'전기 분전반 점유','system-seed') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 4. 서류 폐루프 — 마감 임박(D-3) 필수 서류 순증 (홈 '서류 D-3' 할 일 활성화) +-- V14 기존 서류 due=2026-08-04(고정)는 배포 시점 무관하게 임박하지 않으므로 +-- 상대일(CURRENT_DATE+3) 신규 doc_type 1건 추가. +-- ============================================================================ +INSERT INTO required_document (id, event_id, doc_type, name, status, due_date, sort_order) VALUES + ('doc-smf-reinspect','e-2026-smf','safety_reinspection','전기안전 재점검 확인서','draft', CURRENT_DATE + 3, 8) +ON CONFLICT (event_id, doc_type) DO NOTHING; + + +-- ============================================================================ +-- 5. 옥션 폐루프 — 응찰 보강(3~5씩) + 낙찰 선정 대기 옥션 신설(AUC-2026-0511) +-- 기존 V16: AUC-0102(3응찰·진행), AUC-0405(2응찰·진행), AUC-0210(2응찰·낙찰완료). +-- ============================================================================ +-- 5-1) 기존 옥션 초대·응찰 보강 ----------------------------------------------- +INSERT INTO auction_invite (id, auction_id, company_id) VALUES + ('ai-0405-3', 'AUC-2026-0405', 'co-0001'), + ('ai-0405-4', 'AUC-2026-0405', 'co-0005'), + ('ai-0210-2', 'AUC-2026-0210', 'co-0002') +ON CONFLICT (auction_id, company_id) DO NOTHING; + +INSERT INTO bid (id, auction_id, company_id, round, subtotal, vat, total, lead_days) VALUES + ('bid-0405-3', 'AUC-2026-0405', 'co-0001', 1, 4400000, 440000, 4400000, 7), + ('bid-0405-4', 'AUC-2026-0405', 'co-0005', 1, 4780000, 478000, 4780000, 10), + ('bid-0210-3', 'AUC-2026-0210', 'co-0002', 1, 12500000, 1250000, 12500000, 16) +ON CONFLICT (auction_id, company_id) DO NOTHING; + +-- 5-2) 낙찰 선정 대기 옥션(마감 경과 + 낙찰 미확정) — 홈 '옥션 낙찰 선정' 할 일 활성화 ----- +INSERT INTO auction (id, event_id, title, category, auction_type, award_criteria, + weight_price, weight_reputation, weight_delivery, round, deadline, + material_package_id, materials, accent, created_by) VALUES + ('AUC-2026-0511', 'e-2026-smf', 'D-1 옥외 사이니지 설치', '영상/음향', 'reverse', 'comprehensive', + 55, 25, 20, 1, now() - interval '1 day', NULL, 'layout,boq', 'primary', 'demo-organizer') +ON CONFLICT (id) DO NOTHING; + +INSERT INTO auction_invite (id, auction_id, company_id) VALUES + ('ai-0511-1', 'AUC-2026-0511', 'co-0001'), + ('ai-0511-2', 'AUC-2026-0511', 'co-0002'), + ('ai-0511-3', 'AUC-2026-0511', 'co-0005'), + ('ai-0511-4', 'AUC-2026-0511', 'co-0006') +ON CONFLICT (auction_id, company_id) DO NOTHING; + +INSERT INTO bid (id, auction_id, company_id, round, subtotal, vat, total, lead_days) VALUES + ('bid-0511-1', 'AUC-2026-0511', 'co-0001', 1, 6800000, 680000, 6800000, 9), + ('bid-0511-2', 'AUC-2026-0511', 'co-0002', 1, 7100000, 710000, 7100000, 8), + ('bid-0511-3', 'AUC-2026-0511', 'co-0005', 1, 6500000, 650000, 6500000, 11), + ('bid-0511-4', 'AUC-2026-0511', 'co-0006', 1, 6950000, 695000, 6950000, 10) +ON CONFLICT (auction_id, company_id) DO NOTHING; + + +-- ============================================================================ +-- 6. 관람객·리드 폐루프 +-- ============================================================================ +-- 6-1) 관람객 사전등록 순증 — 오늘 체크인 분포(홈 KPI todayCheckins 활성화) ---------- +-- checkin_at 은 CURRENT_DATE 기준 상대(now()) — 재배포 시점의 '오늘'로 집계. +INSERT INTO visitor_registration + (id, event_id, name, phone, email, company, visitor_type, agree_privacy, agree_marketing, + badge_code, badge_issued, checkin_state, qr_token, checkin_at, registered_at) VALUES + ('vr-smf-101','e-2026-smf','조민준','010-0000-1101','visitor101@kintex.test','(주)스마트오토메이션','buyer', true,true, 'KTX-V-0101',true,'done', 'QR-DEMO0000000000000101', now()-interval '3 hour', now()-interval '2 day'), + ('vr-smf-102','e-2026-smf','윤서아','010-0000-1102','visitor102@kintex.test','델타로보틱스', 'visitor',true,true, 'KTX-V-0102',true,'done', 'QR-DEMO0000000000000102', now()-interval '2 hour', now()-interval '2 day'), + ('vr-smf-103','e-2026-smf','임도현','010-0000-1103','visitor103@kintex.test','한국센서테크', 'vip', true,false,'KTX-V-0103',true,'done', 'QR-DEMO0000000000000103', now()-interval '1 hour', now()-interval '1 day'), + ('vr-smf-104','e-2026-smf','장하윤','010-0000-1104','visitor104@kintex.test',NULL, 'visitor',true,true, 'KTX-V-0104',true,'done', 'QR-DEMO0000000000000104', now()-interval '30 minute', now()-interval '1 day'), + ('vr-smf-105','e-2026-smf','서지호','010-0000-1105','visitor105@kintex.test','넥스트이노베이션', 'buyer', true,true, 'KTX-V-0105',true,'waiting', 'QR-DEMO0000000000000105', NULL, now()-interval '1 day'), + ('vr-smf-106','e-2026-smf','오예린','010-0000-1106','visitor106@kintex.test','글로벌테크', 'visitor',true,false,'KTX-V-0106',false,'waiting','QR-DEMO0000000000000106', NULL, now()-interval '6 hour'), + ('vr-smf-demo','e-2026-smf','데모 관람객(박관람)','010-0000-0000','demo-visitor@kintex.test',NULL,'visitor',true,true,'KTX-V-DEMO',true,'done','QR-DEMO000000000000DEMO', now()-interval '90 minute', now()-interval '3 day') +ON CONFLICT (id) DO NOTHING; + +-- 6-2) 리드 순증 — 총 15건(기존 5 + 신규 10), 핫(score>=80) 총 4건(기존 87·82 + 신규 88·91) --- +INSERT INTO lead + (id, event_id, booth_id, exhibitor_id, name, phone, email, role, company, product, + interest, score, ai_reasons, activity, followup_draft, ai_generated, collected_at) VALUES + ('ld-smf-006','e-2026-smf','booth-smf-b101','demo-exhibitor','문재훈','010-0000-2006','moon@techsol.test','생산기술 팀장','(주)테크솔루션','협동로봇 HR-A1',5,91, + '["부스 체류 18분(평균 대비 300%)","사양서 다운로드 3회","구매 결정권자 직급"]'::jsonb, + '[{"text":"HR-A1 시연 참관","at":"오늘 13:40"},{"text":"견적 요청 폼 제출","at":"오늘 13:55"}]'::jsonb, + '안녕하세요, 문 팀장님. 협동로봇 HR-A1 커스텀 제안서를 준비했습니다. 다음 주 미팅 가능하실까요?', true, now()-interval '5 hour'), + ('ld-smf-007','e-2026-smf','booth-smf-b106','demo-exhibitor','배수진','010-0000-2007','bae@visionind.test','구매 담당','비전인더스트리','AI 비전 검사 모듈',5,88, + '["AI 비전 데모 2회 재방문","경쟁사 대비 견적 문의","도입 시기 명확(Q4)"]'::jsonb, + '[{"text":"AI 비전 모듈 상담","at":"오늘 11:20"}]'::jsonb, + '안녕하세요, 배 님. 요청하신 AI 비전 검사 모듈 견적서와 파일럿 프로그램 안내드립니다.', true, now()-interval '7 hour'), + ('ld-smf-008','e-2026-smf','booth-smf-b101','demo-exhibitor','신유리','010-0000-2008','shin@deltarobo.test','기술 기획','델타로보틱스','스마트 물류',3,63, + '["물류 자동화 세션 참석","브로슈어 다운로드"]'::jsonb, + '[{"text":"데모 영상 시청","at":"오늘 10:10"}]'::jsonb, + '안녕하세요, 신 님. 스마트 물류 도입 사례집을 보내드립니다.', true, now()-interval '9 hour'), + ('ld-smf-009','e-2026-smf','booth-smf-b107',NULL,'홍길동','010-0000-2009','hong@sctsys.test','인프라 엔지니어','SCT시스템','클라우드 모니터링',2,41, + '["짧은 부스 체류","자료 열람 없음"]'::jsonb, + '[{"text":"부스 QR 스캔","at":"오늘 09:50"}]'::jsonb, + '안녕하세요, 홍 님. 클라우드 모니터링 소개서를 보내드립니다.', true, now()-interval '10 hour'), + ('ld-smf-010','e-2026-smf','booth-smf-b109',NULL,'김철수','010-0000-2010','kim@globaltech.test','설비 담당','글로벌테크','자율주행 AMR',2,38, + '["AMR 부스 단순 방문"]'::jsonb, + '[{"text":"부스 QR 스캔","at":"오늘 09:30"}]'::jsonb, + '안녕하세요, 김 님. 자율주행 AMR 소개 자료를 보내드립니다.', true, now()-interval '11 hour'), + ('ld-smf-011','e-2026-smf','booth-smf-b111',NULL,'이영희','010-0000-2011','lee@fmlab.test','연구원','미래제조연구소','스마트 팩토리 컨설팅',4,72, + '["연구 목적 방문","기술 세션 2회 참석"]'::jsonb, + '[{"text":"기술 상담","at":"오늘 14:30"}]'::jsonb, + '안녕하세요, 이 연구원님. 스마트 팩토리 컨설팅 자료를 보내드립니다.', true, now()-interval '3 hour'), + ('ld-smf-012','e-2026-smf','booth-smf-b104',NULL,'박영수','010-0000-2012','park@sensortech.test','품질 담당','한국센서테크','센서 모듈',3,58, + '["센서 데모 관람","카탈로그 수령"]'::jsonb, + '[{"text":"카탈로그 QR 스캔","at":"오늘 12:05"}]'::jsonb, + '안녕하세요, 박 님. 센서 모듈 카탈로그를 보내드립니다.', true, now()-interval '6 hour'), + ('ld-smf-013','e-2026-smf','booth-smf-b102',NULL,'정미경','010-0000-2013','jung@nextinno.test','마케팅','넥스트이노베이션','AI 솔루션',3,55, + '["부스 방문","명함 교환"]'::jsonb, + '[{"text":"명함 교환","at":"오늘 15:10"}]'::jsonb, + '안녕하세요, 정 님. AI 솔루션 소개서를 보내드립니다.', true, now()-interval '2 hour'), + ('ld-smf-014','e-2026-smf','booth-smf-b106',NULL,'최동욱','010-0000-2014','choi@biohealth.test','R&D','바이오헬스랩','자동화 장비',4,74, + '["자동화 장비 상담","도입 검토 중"]'::jsonb, + '[{"text":"장비 상담","at":"오늘 13:00"}]'::jsonb, + '안녕하세요, 최 님. 자동화 장비 제안서를 보내드립니다.', true, now()-interval '4 hour'), + ('ld-smf-015','e-2026-smf','booth-smf-b109',NULL,'강민석','010-0000-2015','kang@doosandemo.test','생산관리','두산로보틱스데모','협동로봇',3,49, + '["로봇 부스 방문"]'::jsonb, + '[{"text":"부스 QR 스캔","at":"오늘 11:45"}]'::jsonb, + '안녕하세요, 강 님. 협동로봇 소개 자료를 보내드립니다.', true, now()-interval '8 hour') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 7. 마케팅 — EDM 캠페인 순증 2 (기존 V18 4건 + 2) +-- ============================================================================ +INSERT INTO edm_campaign (id, event_id, name, status, audience, meta, open_rate, click_rate) VALUES + ('cp-smf-005','e-2026-smf','참가업체 부스 배정 확정 안내','scheduled', 512, '발송 예정: D-2 10:00', '-', '-'), + ('cp-smf-006','e-2026-smf','현장 방문객 만족도 조사','draft', 0, '최종 수정: 방금 전', '-', '-') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 8. 정산 폐루프 — 청구서 순증 4(총 8, 옥션 수수료 1 포함) + 수납/세금계산서/환불 +-- 기존 V24 4건(paid·invoiced·overdue·pending). 순증 4 = paid·partial·cancelled·auction_fee. +-- ============================================================================ +INSERT INTO invoice (id, event_id, exhibitor_id, exhibitor_name, invoice_no, category, source_ref, + subtotal, vat, total, paid_amount, status, due_date, issued_at, paid_at, + cancelled_at, cancel_reason, line_items, note, created_by) VALUES + -- 완납 + ('inv-smf-0005','e-2026-smf',NULL,'(주)테크솔루션','SMF-2026-0005','rental',NULL, + 7920000, 792000, 8712000, 8712000, 'paid', DATE '2026-07-20', now()-interval '22 day', now()-interval '6 day', + NULL, NULL, + '[{"category":"RENTAL","description":"부스 임대료 (72㎡ · B-107)","quantity":72,"unitPrice":110000,"amount":7920000}]'::jsonb, + '완납 처리.', 'system-seed'), + -- 부분수납 + ('inv-smf-0006','e-2026-smf',NULL,'넥스트이노베이션','SMF-2026-0006','rental',NULL, + 10800000, 1080000, 11880000, 4752000, 'invoiced', DATE '2026-07-28', now()-interval '10 day', NULL, + NULL, NULL, + '[{"category":"RENTAL","description":"부스 임대료 (108㎡ · B-109)","quantity":108,"unitPrice":100000,"amount":10800000}]'::jsonb, + '계약금 40% 수납.', 'system-seed'), + -- 취소(환불 대상) — 계약금 납입 후 취소 + ('inv-smf-0007','e-2026-smf',NULL,'미래제조연구소','SMF-2026-0007','rental',NULL, + 6000000, 600000, 6600000, 2640000, 'cancelled', DATE '2026-07-30', now()-interval '14 day', NULL, + now()-interval '3 day', '참가 철회(내부 사정) — 환불 규정 적용', + '[{"category":"RENTAL","description":"부스 임대료 (54㎡ · B-111)","quantity":54,"unitPrice":111111,"amount":6000000}]'::jsonb, + '취소 확정 — 환불 산정 대상.', 'system-seed'), + -- 옥션 낙찰 수수료(F084) — AUC-2026-0210 낙찰(aw-0210, co-0003) 5% 수수료 + ('inv-smf-0008','e-2026-smf',NULL,'세계전기시설','SMF-2026-0008','auction_fee','aw-0210', + 600000, 60000, 660000, 0, 'pending', DATE '2026-08-05', NULL, NULL, + NULL, NULL, + '[{"category":"AUCTION_FEE","description":"옥션 낙찰 수수료 5% (AUC-2026-0210 · 낙찰 12,000,000원)","quantity":1,"unitPrice":600000,"amount":600000}]'::jsonb, + '옥션 낙찰 수수료 청구(발행 대기).', 'system-seed') +ON CONFLICT (id) DO NOTHING; + +-- 수납 기록(inv-0005 완납 · inv-0006 부분 · inv-0007 취소 전 계약금) -------------------- +INSERT INTO invoice_payment (id, invoice_id, amount, method, memo, recorded_by, recorded_at) VALUES + ('pay-smf-0005-1','inv-smf-0005', 8712000, 'transfer', '일시 완납', 'system-seed', now()-interval '6 day'), + ('pay-smf-0006-1','inv-smf-0006', 4752000, 'transfer', '계약금 40%', 'system-seed', now()-interval '7 day'), + ('pay-smf-0007-1','inv-smf-0007', 2640000, 'transfer', '계약금 40%(취소 전 납입)', 'system-seed', now()-interval '12 day') +ON CONFLICT (id) DO NOTHING; + +-- 세금계산서(F083) 1건 — 완납 청구 inv-smf-0001 기반 ----------------------------------- +INSERT INTO tax_invoice (tenant_id, id, invoice_id, event_id, tax_invoice_no, + supplier_name, supplier_biz_no, supplier_ceo, supplier_addr, + buyer_name, supply_amount, vat, total, item_summary, status, issued_by) VALUES + ('KINTEX','tax-smf-0001','inv-smf-0001','e-2026-smf','TAX-2026-0001', + '킨텍스(KINTEX)','128-81-00000','대표이사','경기도 고양시 일산서구 킨텍스로 217', + '(주)스마트오토메이션', 18000000, 1800000, 19800000, '부스 임대료 외 (108㎡ · A-101)', 'issued', 'system-seed') +ON CONFLICT (id) DO NOTHING; + +-- 환불(F085) 1건 — 취소 청구 inv-smf-0007 기준. base=실납입(2,640,000), 개막 D-일 구간 환불율 적용 ---- +INSERT INTO invoice_refund (tenant_id, id, invoice_id, event_id, base_amount, refund_rate_percent, + refund_amount, forfeit_amount, days_before_event, bracket_label, + reason, ruleset_version, status, created_by) VALUES + ('KINTEX','ref-smf-0007','inv-smf-0007','e-2026-smf', 2640000, 50.00, + 1320000, 1320000, (DATE '2026-08-11' - (CURRENT_DATE - 3)), '개막 30~15일 전(50%)', + '참가 철회 — 환불 규정(refund-v1.0) 구간 적용', 'refund-v1.0', 'recorded', 'system-seed') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 9. 전자결재 폐루프 — 문서 5 (demo-organizer 가 현재 단계 결재자 → 홈 '결재 대기' 활성화) +-- 상태: SUBMITTED×2 · IN_PROGRESS×1 · APPROVED×1 · DRAFT×1 +-- ★ approver 는 demo-organizer(결정론적). env 관리자(ADMIN)는 broad KPI(서류·미수·낙찰)로 별도 활성. +-- ============================================================================ +INSERT INTO approval (tenant_id, id, event_id, doc_type, title, content, ref_type, ref_id, + drafter_id, drafter_name, status, cur_step, version, submitted_at, completed_at) VALUES + ('KINTEX','ap-smf-01','e-2026-smf','GENERAL','부스 B-101 설계안 승인 요청','A-102 독립부스 최종 설계안(3.5m 높이) 승인 요청.','DOCUMENT','booth-smf-b101', + 'demo-exhibitor','데모 참가업체(김참가)','SUBMITTED',1,1, now()-interval '2 day', NULL), + ('KINTEX','ap-smf-02','e-2026-smf','GENERAL','유틸리티 신청 승인 요청','전기·네트워크 유틸리티 신청 검토 승인 요청.','DOCUMENT','uo-smf-a102', + 'demo-exhibitor','데모 참가업체(김참가)','SUBMITTED',1,1, now()-interval '1 day', NULL), + ('KINTEX','ap-smf-03','e-2026-smf','GENERAL','옥션 낙찰 결과 승인(AUC-0210)','C-10 통로 조명 공사 낙찰(세계전기시설) 결과 승인.','GENERAL',NULL, + 'demo-contractor','데모 공사업체(이시공)','IN_PROGRESS',2,1, now()-interval '3 day', NULL), + ('KINTEX','ap-smf-04','e-2026-smf','GENERAL','재해대처계획서 검수 승인','재해대처계획서 최종본 검수 승인(완료).','DOCUMENT','disaster_plan', + 'demo-exhibitor','데모 참가업체(김참가)','APPROVED',1,1, now()-interval '5 day', now()-interval '4 day'), + ('KINTEX','ap-smf-05','e-2026-smf','GENERAL','스폰서십 계약 품의(임시저장)','다이아몬드 스폰서 계약 품의 초안.','GENERAL',NULL, + 'demo-organizer','데모 주최자(홍길동)','DRAFT',0,1, NULL, NULL) +ON CONFLICT (id) DO NOTHING; + +INSERT INTO approval_line (tenant_id, id, approval_id, step_no, approver_id, approver_name, line_status, acted_at, comment) VALUES + -- ap-01: 1단계 CURRENT = demo-organizer + ('KINTEX','al-smf-01-1','ap-smf-01',1,'demo-organizer','데모 주최자(홍길동)','CURRENT',NULL,NULL), + -- ap-02: 1단계 CURRENT = demo-organizer + ('KINTEX','al-smf-02-1','ap-smf-02',1,'demo-organizer','데모 주최자(홍길동)','CURRENT',NULL,NULL), + -- ap-03: 1단계 APPROVED(demo-exhibitor) → 2단계 CURRENT = demo-organizer + ('KINTEX','al-smf-03-1','ap-smf-03',1,'demo-exhibitor','데모 참가업체(김참가)','APPROVED', now()-interval '2 day','1차 확인 완료'), + ('KINTEX','al-smf-03-2','ap-smf-03',2,'demo-organizer','데모 주최자(홍길동)','CURRENT',NULL,NULL), + -- ap-04: 1단계 APPROVED(demo-organizer) → 종결 + ('KINTEX','al-smf-04-1','ap-smf-04',1,'demo-organizer','데모 주최자(홍길동)','APPROVED', now()-interval '4 day','검수 승인'), + -- ap-05: DRAFT — 결재선 1단계 WAIT + ('KINTEX','al-smf-05-1','ap-smf-05',1,'demo-organizer','데모 주최자(홍길동)','WAIT',NULL,NULL) +ON CONFLICT (tenant_id, id) DO NOTHING; + +INSERT INTO approval_history (tenant_id, id, approval_id, step_no, actor_id, actor_name, action, comment, acted_at) VALUES + ('KINTEX','ah-smf-01-1','ap-smf-01',1,'demo-exhibitor','데모 참가업체(김참가)','SUBMIT','설계안 상신', now()-interval '2 day'), + ('KINTEX','ah-smf-02-1','ap-smf-02',1,'demo-exhibitor','데모 참가업체(김참가)','SUBMIT','유틸리티 신청 상신', now()-interval '1 day'), + ('KINTEX','ah-smf-03-1','ap-smf-03',1,'demo-contractor','데모 공사업체(이시공)','SUBMIT','낙찰 승인 상신', now()-interval '3 day'), + ('KINTEX','ah-smf-03-2','ap-smf-03',1,'demo-exhibitor','데모 참가업체(김참가)','APPROVE','1차 확인 완료', now()-interval '2 day'), + ('KINTEX','ah-smf-04-1','ap-smf-04',1,'demo-exhibitor','데모 참가업체(김참가)','SUBMIT','계획서 검수 상신', now()-interval '5 day'), + ('KINTEX','ah-smf-04-2','ap-smf-04',1,'demo-organizer','데모 주최자(홍길동)','APPROVE','검수 승인', now()-interval '4 day') +ON CONFLICT (tenant_id, id) DO NOTHING; + + +-- ============================================================================ +-- 10. 공지(notice) 6 + 알림(notification) + 업무일지/일정(§5B) +-- ============================================================================ +INSERT INTO notice (id, event_id, category, title, content, pinned, author_id, author_name, view_count, published_at) VALUES + ('nt-smf-01','e-2026-smf','SYSTEM','[중요] 2026 스마트팩토리 코리아 반입 일정 안내','반입은 개막 D-2 09:00부터 가능합니다. 차량 등록 필수.', true, 'demo-organizer','데모 주최자(홍길동)', 342, now()-interval '5 day'), + ('nt-smf-02','e-2026-smf','EVENT','참가업체 필수 서류 제출 마감 안내','재해대처계획서·리깅 구조계산서 마감이 임박했습니다. 기한 내 제출 바랍니다.', true, 'demo-organizer','데모 주최자(홍길동)', 288, now()-interval '3 day'), + ('nt-smf-03','e-2026-smf','GENERAL','부스 장치공사 안전관리 지침','장치물 최고 높이 5m, 리깅 허용 6.5~8.5m 준수 바랍니다.', false, 'demo-organizer','데모 주최자(홍길동)', 156, now()-interval '2 day'), + ('nt-smf-04','e-2026-smf','GENERAL','전기·네트워크 유틸리티 신청 마감 안내','유틸리티 신청은 개막 D-7까지 접수합니다.', false, 'demo-organizer','데모 주최자(홍길동)', 121, now()-interval '2 day'), + ('nt-smf-05','e-2026-smf','EVENT','VIP 바이어 네트워킹 데이 안내','개막 2일차 오후 네트워킹 라운지 운영.', false, 'demo-organizer','데모 주최자(홍길동)', 98, now()-interval '1 day'), + ('nt-smf-06',NULL,'SYSTEM','[시스템] 정기 점검 안내','매주 일요일 02:00~04:00 정기 점검이 진행됩니다.', false, 'demo-organizer','데모 주최자(홍길동)', 64, now()-interval '6 hour') +ON CONFLICT (id) DO NOTHING; + +INSERT INTO notification (id, recipient_id, event_id, noti_type, title, message, link, read_at) VALUES + ('no-smf-01','demo-organizer','e-2026-smf','APPROVAL','결재 대기 문서','부스 B-101 설계안 승인 요청이 도착했습니다.', '/work/approval', NULL), + ('no-smf-02','demo-organizer','e-2026-smf','DEADLINE','서류 마감 임박','전기안전 재점검 확인서 마감 D-3.', '/docs', NULL), + ('no-smf-03','demo-organizer','e-2026-smf','SYSTEM','옥션 낙찰 선정 대기','D-1 옥외 사이니지 설치 옥션 마감 — 낙찰 선정이 필요합니다.', '/auctions/AUC-2026-0511/award', NULL), + ('no-smf-04','demo-contractor','e-2026-smf','DEADLINE','응찰 마감 임박','A-102 독립부스 시공 응찰 마감 D-2.', '/auctions/AUC-2026-0102', NULL), + ('no-smf-05','demo-exhibitor','e-2026-smf','MESSAGE','부스 배정 확정','B-101 부스가 배정되었습니다.', '/booth-sales', now()-interval '1 day') +ON CONFLICT (id) DO NOTHING; + +INSERT INTO worklog (id, event_id, writer_id, writer_name, dept_id, work_date, title, work_type, progress, status, content, hours) VALUES + ('wl-smf-01','e-2026-smf','demo-organizer','데모 주최자(홍길동)','d-hall', CURRENT_DATE, '홀 배치 확정 및 판매 오픈','OPERATION','P100','DONE','H7 데모 배치 12부스 판매 상태 설정 완료.', 4.0), + ('wl-smf-02','e-2026-smf','demo-organizer','데모 주최자(홍길동)','d-hall', CURRENT_DATE-1, '서류 검수 및 결재 상신','OPERATION','P75','DOING','필수 서류 검수 진행, 재해대처계획서 반려 후 재요청.', 3.5), + ('wl-smf-03','e-2026-smf','demo-organizer','데모 주최자(홍길동)','d-hall', CURRENT_DATE-2, '옥션 3건 응찰 현황 점검','OPERATION','P50','DOING','AUC-0102/0405/0210 응찰 모니터링.', 2.5) +ON CONFLICT (id) DO NOTHING; + +INSERT INTO schedule (id, event_id, owner_id, owner_name, dept_id, title, schedule_type, importance, start_at, end_at, all_day, location, content) VALUES + ('sc-smf-01','e-2026-smf','demo-organizer','데모 주최자(홍길동)','d-hall','주최자 운영 회의','TEAM','HIGH', now()+interval '1 day', now()+interval '1 day 1 hour', false, '킨텍스 제1전시장 회의실', '개막 준비 점검 회의'), + ('sc-smf-02','e-2026-smf','demo-organizer','데모 주최자(홍길동)','d-hall','옥션 낙찰 선정','EVENT','URGENT', now()+interval '2 hour', now()+interval '3 hour', false, '온라인', 'AUC-2026-0511 낙찰 선정'), + ('sc-smf-03','e-2026-smf','demo-organizer','데모 주최자(홍길동)','d-hall','반입 리허설','EVENT','NORMAL', now()+interval '5 day', now()+interval '5 day 4 hour', false, '킨텍스 제2전시장 H7', '반입 동선 리허설') +ON CONFLICT (id) DO NOTHING; + +-- ============================================================================ +-- 검증 쿼리(수동 실행용 — 마이그레이션에는 포함되지 않는 주석): +-- -- 데모 계정: SELECT id,email,role_code,otp_enabled FROM app_user WHERE email LIKE '%@kintex.test'; +-- -- demo-organizer 결재대기: SELECT count(*) FROM approval_line al JOIN approval a ON a.id=al.approval_id +-- -- WHERE al.approver_id='demo-organizer' AND al.line_status='CURRENT' AND a.status IN('SUBMITTED','IN_PROGRESS'); -- 기대 3 +-- -- 서류 D-7 이내 미승인: SELECT count(*) FROM required_document WHERE event_id='e-2026-smf' +-- -- AND status<>'approved' AND due_date IS NOT NULL AND due_date<=CURRENT_DATE+7; -- >=1 (doc-smf-reinspect) +-- -- 낙찰 미확정 마감경과 옥션: SELECT count(*) FROM auction a WHERE a.deadline=1 (AUC-2026-0511) +-- -- 오늘 체크인: SELECT count(*) FROM visitor_registration WHERE checkin_at::date=CURRENT_DATE; -- 5 +-- -- 미수 청구: SELECT count(*) FROM invoice i JOIN event e ON e.id=i.event_id +-- -- WHERE e.tenant_id='KINTEX' AND i.status IN('pending','overdue'); -- >=3 +-- -- 부스 판매분포: SELECT status,count(*) FROM booth_sale WHERE event_id='e-2026-smf' GROUP BY status; +-- -- 리드 15/핫4: SELECT count(*), count(*) FILTER(WHERE score>=80) FROM lead WHERE event_id='e-2026-smf'; +-- ============================================================================ diff --git a/src/backend/src/test/java/com/zioinfo/kintex/mail/MailServiceTest.java b/src/backend/src/test/java/com/zioinfo/kintex/mail/MailServiceTest.java new file mode 100644 index 0000000..8e49453 --- /dev/null +++ b/src/backend/src/test/java/com/zioinfo/kintex/mail/MailServiceTest.java @@ -0,0 +1,87 @@ +package com.zioinfo.kintex.mail; + +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.mail.javamail.JavaMailSender; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +/** + * MailService/MailBatch 단위 테스트 — ①비활성(MAIL_ENABLED=false) 스킵 ②수신자 마스킹 ③배치 분할. + * SMTP 연동 없이 순수 로직만 검증한다. + */ +class MailServiceTest { + + @SuppressWarnings("unchecked") + private ObjectProvider providerOf(JavaMailSender sender) { + ObjectProvider p = mock(ObjectProvider.class); + when(p.getIfAvailable()).thenReturn(sender); + return p; + } + + @Test + void disabled_skips_actual_send_and_records_skipped() { + MailProperties props = new MailProperties(); + props.setEnabled(false); // MAIL_ENABLED=false + JavaMailSender sender = mock(JavaMailSender.class); + MailLogMapper mapper = mock(MailLogMapper.class); + + MailService svc = new MailService(props, providerOf(sender), mapper); + svc.send("AUCTION_OPEN", "AUC-1", "kimchulsu@domain.com", "제목", "

body

"); + + // 실제 SMTP 전송은 발생하지 않는다. + verify(sender, never()).send(any(jakarta.mail.internet.MimeMessage.class)); + // 이력은 skipped 상태 + 마스킹 수신자로 기록. + ArgumentCaptor statusCap = ArgumentCaptor.forClass(String.class); + ArgumentCaptor recipientCap = ArgumentCaptor.forClass(String.class); + verify(mapper).insert(anyString(), eq("AUCTION_OPEN"), eq("AUC-1"), anyString(), + recipientCap.capture(), statusCap.capture(), any()); + assertThat(statusCap.getValue()).isEqualTo("skipped"); + assertThat(recipientCap.getValue()).isEqualTo("kim***@domain.com"); + } + + @Test + void sender_absent_also_skips() { + MailProperties props = new MailProperties(); + props.setEnabled(true); // 켜져 있어도 sender 없으면 스킵 + MailLogMapper mapper = mock(MailLogMapper.class); + + MailService svc = new MailService(props, providerOf(null), mapper); + svc.send("EDM", "cp-1", "a@b.com", "제목", "

body

"); + + verify(mapper).insert(anyString(), eq("EDM"), eq("cp-1"), anyString(), + anyString(), eq("skipped"), any()); + } + + @Test + void maskEmail_masks_local_part() { + assertThat(MailService.maskEmail("kimchulsu@domain.com")).isEqualTo("kim***@domain.com"); + assertThat(MailService.maskEmail("ab@x.com")).isEqualTo("a***@x.com"); + assertThat(MailService.maskEmail(null)).isEqualTo("***"); + assertThat(MailService.maskEmail("noatsign")).isEqualTo("***"); + } + + @Test + void batch_partitions_by_size() { + List items = new java.util.ArrayList<>(); + for (int i = 0; i < 120; i++) { + items.add(i); + } + List> batches = MailBatch.partition(items, 50); + assertThat(batches).hasSize(3); + assertThat(batches.get(0)).hasSize(50); + assertThat(batches.get(1)).hasSize(50); + assertThat(batches.get(2)).hasSize(20); + } + + @Test + void batch_empty_and_nonpositive() { + assertThat(MailBatch.partition(List.of(), 50)).isEmpty(); + assertThat(MailBatch.partition(List.of(1, 2, 3), 0)).hasSize(1); + } +} diff --git a/src/backend/src/test/java/com/zioinfo/kintex/security/LoginAttemptServiceTest.java b/src/backend/src/test/java/com/zioinfo/kintex/security/LoginAttemptServiceTest.java index 9f81827..1bdae45 100644 --- a/src/backend/src/test/java/com/zioinfo/kintex/security/LoginAttemptServiceTest.java +++ b/src/backend/src/test/java/com/zioinfo/kintex/security/LoginAttemptServiceTest.java @@ -2,6 +2,7 @@ package com.zioinfo.kintex.security; import com.zioinfo.kintex.common.error.ApiException; import com.zioinfo.kintex.common.error.ErrorCode; +import com.zioinfo.kintex.system.loginhistory.LoginHistoryService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -32,7 +33,7 @@ class LoginAttemptServiceTest { SecurityPolicyProperties props = new SecurityPolicyProperties(); props.getLockout().setMaxFailedAttempts(5); props.getLockout().setLockMinutes(30); - service = new LoginAttemptService(mapper, props); + service = new LoginAttemptService(mapper, props, mock(LoginHistoryService.class)); } private Map row(int failedCount, OffsetDateTime lockedUntil) { diff --git a/src/frontend/index.html b/src/frontend/index.html index c112d37..b26bfff 100644 --- a/src/frontend/index.html +++ b/src/frontend/index.html @@ -3,7 +3,7 @@ - KINTEX AI 전시관리 + KINTEX AI 전시·행사시스템 {children}; } +/** 루트/미매칭 분기 — 인증=홈, 미인증=공개 소개 랜딩(제품 아이덴티티, 2026-07-12 소유자 지적). */ +function RootGate() { + const isAuthenticated = useAuthStore((s) => s.isAuthenticated); + return ; +} + export function App() { return ( @@ -156,6 +172,8 @@ export function App() { } /> {/* F005/F006 부스 판매(셀프 선택) */} } /> + {/* 모바일 앱 설치 QR (WISE AppQrCode 패턴) */} + } /> {/* §5B 전자결재 결재함(F028) — 홈 내 할 일 route 정합(/work/approval) */} } /> {/* SCR-15 전시 일정 관리 (M1·M6) */} @@ -213,6 +231,17 @@ export function App() { } /> } /> } /> + {/* W12 WISE 시스템관리 기본기 8종 (V37) */} + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> {/* SCR-P1~P7 공개 홍보 사이트 — 비로그인, 자체 PublicShell */} @@ -239,7 +268,8 @@ export function App() { } /> - } /> + } /> + } /> ); } diff --git a/src/frontend/src/components/layout/AppShell.tsx b/src/frontend/src/components/layout/AppShell.tsx index 6a0184f..d7b0b67 100644 --- a/src/frontend/src/components/layout/AppShell.tsx +++ b/src/frontend/src/components/layout/AppShell.tsx @@ -1,9 +1,12 @@ import type { ComponentType } from 'react'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { NavLink, Outlet, useLocation, useNavigate } from 'react-router-dom'; import { useAuthStore } from '../../store/authStore'; import { useThemeStore } from '../../store/themeStore'; import { useMdiStore } from '../../store/mdiStore'; +import { useUiStore, isMobileViewport } from '../../store/uiStore'; +import { useIsAdmin } from '../../screens/admin/AdminGuard'; import { MdiTabBar } from './MdiTabBar'; import { ShellFooter } from './ShellFooter'; import { labelForPath } from './mdiLabels'; @@ -15,17 +18,21 @@ import { IconBell, IconCalendar, IconCheckCircle, + IconChevronDown, IconDashboard, IconDocument, IconExhibitors, IconFloorplan, + IconGrid, IconHome, + IconLogOut, + IconMenu, IconMoon, IconOperations, - IconSearch, IconSettings, IconSettlement, IconSun, + IconUser, IconUsers, type IconProps, } from '../ui/icons'; @@ -34,71 +41,181 @@ import './app-shell.css'; /** * 사이드바 항목. `to`가 있으면 react-router NavLink(활성 표시). * `scoped: true` 항목(대시보드·플로어플랜·참가업체)은 행사 스코프(:eventId) 라우트라 - * 정적 to 로 배선할 수 없다 → 클릭 시 useResolvedEventId 로 대상 행사를 해소해 계산된 경로로 이동하고, - * 해소 불가(참여 행사 없음) 시 행사 선택 화면(/login 워크스페이스 그리드)으로 보낸다. + * 정적 to 로 배선할 수 없다 → 클릭 시 useResolvedEventId 로 대상 행사를 해소해 계산된 경로로 이동한다. */ -const NAV_ITEMS: { +interface NavItem { key: string; + /** 링크 라벨(또는 section=true 인 경우 소그룹 구분 헤더 텍스트) — i18n 미해소 시 폴백. */ label: string; - Icon: ComponentType; + /** i18n 키(shell.menu.*). 없으면 label 을 그대로 사용. */ + labelKey?: string; + /** 서브항목은 아이콘 대신 점(dot)으로 렌더 — Icon 은 메타(선택). */ + Icon?: ComponentType; to?: string; scoped?: boolean; -}[] = [ - // 메인 홈(SCR-HOME) — 로그인 후 랜딩. 라우트 /home 배선은 통합자(App.tsx) 소관. - { key: 'home', label: '홈', Icon: IconHome, to: '/home' }, - { key: 'dashboard', label: '대시보드', Icon: IconDashboard, scoped: true }, - { key: 'floorplan', label: '플로어플랜 스튜디오', Icon: IconFloorplan, scoped: true }, - { key: 'exhibitors', label: '참가업체 관리', Icon: IconExhibitors, scoped: true }, - { key: 'schedule', label: '전시 일정', Icon: IconCalendar, to: '/schedule' }, - { key: 'operations', label: '현장운영', Icon: IconOperations, to: '/ops/operations' }, - { key: 'analytics', label: '경영분석', Icon: IconAnalytics, to: '/analytics' }, - { key: 'documents', label: '서류·마일스톤', Icon: IconDocument, to: '/docs' }, - // 정산 — 이번 웨이브 신설. 라우트(/settlement)는 통합자가 App.tsx 에 배선(요청서 §통합자 배선). - { key: 'settlement', label: '정산', Icon: IconSettlement, to: '/settlement' }, - { key: 'admin', label: '관리자', Icon: IconSettings, to: '/admin' }, + /** true → 클릭 불가한 소그룹 구분 헤더(시스템관리 20항목 정리용). */ + section?: boolean; +} +interface NavGroupDef { + id: string; + label: string; + labelKey?: string; + Icon: ComponentType; + items: NavItem[]; + /** 관리자 전용 그룹 — useIsAdmin() 시에만 노출. */ + admin?: boolean; +} + +/** 홈 — 로그인 후 랜딩(단일 최상위 링크, 아코디언 밖). */ +const HOME_ITEM: NavItem = { key: 'home', label: '홈', labelKey: 'shell.menu.home', Icon: IconHome, to: '/home' }; + +/** + * 전면 IA 재구성(소유자 지시 ③) — 평면 나열 폐기, 의미 그룹으로 재편. + * 전 라우트 누락 없이 재배치. WISE menuTree 처럼 대분류 그룹 아코디언. + * 라벨은 shell.menu.* i18n(4개 언어) 로 해소하고, label 은 폴백(ko). + */ +const GROUPS: NavGroupDef[] = [ + { + id: 'ops', + label: '전시 운영', + labelKey: 'shell.menu.groups.ops', + Icon: IconOperations, + items: [ + { key: 'dashboard', label: '대시보드', labelKey: 'shell.menu.items.dashboard', Icon: IconDashboard, scoped: true }, + { key: 'exhibitors', label: '참가업체 관리', labelKey: 'shell.menu.items.exhibitors', Icon: IconExhibitors, scoped: true }, + { key: 'schedule', label: '전시 일정', labelKey: 'shell.menu.items.schedule', Icon: IconCalendar, to: '/schedule' }, + { key: 'halls', label: '홀 배정', labelKey: 'shell.menu.items.halls', Icon: IconGrid, to: '/halls' }, + { key: 'booth-sales', label: '부스 판매', labelKey: 'shell.menu.items.boothSales', Icon: IconSettlement, to: '/booth-sales' }, + { key: 'operations', label: '현장운영', labelKey: 'shell.menu.items.operations', Icon: IconOperations, to: '/ops/operations' }, + ], + }, + { + id: 'design', + label: '설계·시공', + labelKey: 'shell.menu.groups.design', + Icon: IconFloorplan, + items: [ + { key: 'floorplan', label: '플로어플랜 스튜디오', labelKey: 'shell.menu.items.floorplan', Icon: IconFloorplan, scoped: true }, + { key: 'documents', label: '서류·마일스톤', labelKey: 'shell.menu.items.documents', Icon: IconDocument, to: '/docs' }, + { key: 'auctions', label: '공사 옥션', labelKey: 'shell.menu.items.auctions', Icon: IconSettlement, to: '/auctions' }, + { key: 'contractor', label: '수주 부스', labelKey: 'shell.menu.items.contractor', Icon: IconExhibitors, to: '/contractor/dashboard' }, + { key: 'logistics', label: '반입·반출', labelKey: 'shell.menu.items.logistics', Icon: IconOperations, to: '/logistics' }, + ], + }, + { + id: 'visitor', + label: '관람객·마케팅', + labelKey: 'shell.menu.groups.visitor', + Icon: IconUsers, + items: [ + { key: 'visitors', label: '관람객', labelKey: 'shell.menu.items.visitors', Icon: IconUsers, to: '/visitors' }, + { key: 'checkin', label: '체크인 데스크', labelKey: 'shell.menu.items.checkin', Icon: IconCheckCircle, to: '/visitors/checkin' }, + { key: 'leads', label: '리드', labelKey: 'shell.menu.items.leads', Icon: IconExhibitors, to: '/leads' }, + { key: 'campaigns', label: '마케팅', labelKey: 'shell.menu.items.campaigns', Icon: IconBell, to: '/campaigns' }, + { key: 'sponsorship', label: '스폰서십', labelKey: 'shell.menu.items.sponsorship', Icon: IconSettlement, to: '/sponsorship' }, + { key: 'cms', label: '콘텐츠 CMS', labelKey: 'shell.menu.items.cms', Icon: IconDocument, to: '/cms' }, + ], + }, + { + id: 'finance', + label: '정산·분석', + labelKey: 'shell.menu.groups.finance', + Icon: IconAnalytics, + items: [ + { key: 'settlement', label: '정산', labelKey: 'shell.menu.items.settlement', Icon: IconSettlement, to: '/settlement' }, + { key: 'analytics', label: '경영분석', labelKey: 'shell.menu.items.analytics', Icon: IconAnalytics, to: '/analytics' }, + ], + }, + { + id: 'work', + label: '업무 공통', + labelKey: 'shell.menu.groups.work', + Icon: IconDocument, + items: [ + { key: 'worklog', label: '업무일지', labelKey: 'shell.menu.items.worklog', Icon: IconDocument, to: '/work/worklog' }, + { key: 'work-schedule', label: '일정', labelKey: 'shell.menu.items.workSchedule', Icon: IconCalendar, to: '/work/schedule' }, + { key: 'message', label: '쪽지', labelKey: 'shell.menu.items.message', Icon: IconUsers, to: '/work/message' }, + { key: 'notice', label: '공지', labelKey: 'shell.menu.items.notice', Icon: IconBell, to: '/work/notice' }, + { key: 'meeting', label: '회의록', labelKey: 'shell.menu.items.meeting', Icon: IconOperations, to: '/work/meeting' }, + { key: 'report', label: '업무보고', labelKey: 'shell.menu.items.report', Icon: IconAnalytics, to: '/work/report' }, + { key: 'approval', label: '결재', labelKey: 'shell.menu.items.approval', Icon: IconCheckCircle, to: '/work/approval' }, + { key: 'opinion', label: '의견접수', labelKey: 'shell.menu.items.opinion', Icon: IconCheckCircle, to: '/work/opinion' }, + { key: 'search', label: '통합검색', labelKey: 'shell.menu.items.search', Icon: IconGrid, to: '/work/search' }, + { key: 'app-qr', label: '모바일 앱 설치', labelKey: 'shell.menu.items.appqr', Icon: IconGrid, to: '/app-qr' }, + ], + }, + { + id: 'system', + label: '시스템관리', + labelKey: 'shell.menu.groups.system', + Icon: IconSettings, + admin: true, + items: [ + { key: 'admin', label: '관리 대시보드', labelKey: 'shell.menu.items.admin', Icon: IconDashboard, to: '/admin' }, + // 사용자·조직 + { key: 'sec-userorg', label: '사용자·조직', labelKey: 'shell.menu.sections.userOrg', section: true }, + { key: 'admin-users', label: '사용자 관리', labelKey: 'shell.menu.items.users', Icon: IconUsers, to: '/admin/users' }, + { key: 'admin-roles', label: '역할/권한', labelKey: 'shell.menu.items.roles', Icon: IconCheckCircle, to: '/admin/roles' }, + { key: 'admin-depts', label: '조직 관리', labelKey: 'shell.menu.items.depts', Icon: IconUsers, to: '/admin/depts' }, + { key: 'admin-companies', label: '회사 관리', labelKey: 'shell.menu.items.companies', Icon: IconExhibitors, to: '/admin/companies' }, + // 메뉴·프로그램·코드 + { key: 'sec-menuauth', label: '메뉴·프로그램·코드', labelKey: 'shell.menu.sections.menuAuth', section: true }, + { key: 'admin-menus', label: '메뉴 관리', labelKey: 'shell.menu.items.menus', Icon: IconDocument, to: '/admin/menus' }, + { key: 'admin-programs', label: '프로그램 관리', labelKey: 'shell.menu.items.programs', Icon: IconGrid, to: '/admin/programs' }, + { key: 'admin-role-menus', label: '역할-메뉴 매핑', labelKey: 'shell.menu.items.roleMenus', Icon: IconCheckCircle, to: '/admin/role-menus' }, + { key: 'admin-codes', label: '공통코드', labelKey: 'shell.menu.items.codes', Icon: IconGrid, to: '/admin/codes' }, + // 정책·이력·로그 + { key: 'sec-policylog', label: '정책·이력·로그', labelKey: 'shell.menu.sections.policyLog', section: true }, + { key: 'admin-auth-policy', label: '인증 정책', labelKey: 'shell.menu.items.authPolicy', Icon: IconSettings, to: '/admin/auth-policy' }, + { key: 'admin-login-history', label: '로그인 이력', labelKey: 'shell.menu.items.loginHistory', Icon: IconDocument, to: '/admin/login-history' }, + { key: 'admin-audit', label: '감사로그', labelKey: 'shell.menu.items.audit', Icon: IconDocument, to: '/admin/audit' }, + { key: 'admin-error-log', label: '오류 로그', labelKey: 'shell.menu.items.errorLog', Icon: IconDocument, to: '/admin/error-log' }, + // 상태·설정 + { key: 'sec-statusconfig', label: '상태·설정', labelKey: 'shell.menu.sections.statusConfig', section: true }, + { key: 'admin-system-health', label: '시스템 상태', labelKey: 'shell.menu.items.systemHealth', Icon: IconAnalytics, to: '/admin/system-health' }, + { key: 'admin-settings', label: '시스템설정', labelKey: 'shell.menu.items.settings', Icon: IconSettings, to: '/admin/settings' }, + { key: 'admin-mail-config', label: '메일 설정', labelKey: 'shell.menu.items.mailConfig', Icon: IconBell, to: '/admin/mail-config' }, + { key: 'admin-notify-config', label: '알림 설정', labelKey: 'shell.menu.items.notifyConfig', Icon: IconBell, to: '/admin/notify-config' }, + // 마스터·기타 + { key: 'sec-masteretc', label: '마스터·기타', labelKey: 'shell.menu.sections.masterEtc', section: true }, + { key: 'admin-tenants', label: '테넌트', labelKey: 'shell.menu.items.tenants', Icon: IconExhibitors, to: '/admin/tenants' }, + { key: 'admin-rulesets', label: '룰셋', labelKey: 'shell.menu.items.rulesets', Icon: IconOperations, to: '/admin/masterdata/rulesets' }, + { key: 'admin-slides', label: '로그인 슬라이드', labelKey: 'shell.menu.items.slides', Icon: IconBell, to: '/admin/login-slides' }, + ], + }, ]; /** * 행사 스코프 항목 → 실제 경로 빌더(App.tsx 라우트와 정합). - * 플로어플랜은 홀 id 가 필요하나 워크스페이스에 홀 id 가 없어 기본 홀 'H7' 규약을 따른다 - * (LoginPage.enterWorkspace 와 동일 규약 — 실제 홀 선택은 대시보드에서). - * 참가업체 관리는 전용 라우트 부재 → 참가업체 로스터가 있는 주최자 대시보드로 진입한다 - * (통합자가 /events/:eventId/exhibitors 신설 시 이 빌더만 교체). + * 플로어플랜 홀은 워크스페이스 hallLabel 에서 파싱(예: "제2전시장 홀7" → H7), 실패 시 'H7' 폴백. + * 참가업체는 전용 라우트 부재 → 참가업체 로스터가 있는 주최자 대시보드로(신설 시 교체). */ -const EVENT_SCOPED_PATH: Record string> = { +const EVENT_SCOPED_PATH: Record string> = { dashboard: (id) => `/events/${id}/dashboard`, - floorplan: (id) => `/events/${id}/halls/H7/layout`, + floorplan: (id, hallId) => `/events/${id}/halls/${hallId}/layout`, exhibitors: (id) => `/events/${id}/dashboard`, }; -/** 도메인 모듈(SCR-25~38 이식분) — 백엔드 미구현 모듈은 화면에 "샘플 데이터" 배지 표기. */ -const DOMAIN_NAV: { key: string; label: string; Icon: ComponentType; to: string }[] = [ - { key: 'halls', label: '홀 배정', Icon: IconFloorplan, to: '/halls' }, - { key: 'logistics', label: '반입·반출', Icon: IconOperations, to: '/logistics' }, - { key: 'auctions', label: '공사 옥션', Icon: IconSettlement, to: '/auctions' }, - { key: 'visitors', label: '관람객', Icon: IconUsers, to: '/visitors' }, - { key: 'checkin', label: '체크인 데스크', Icon: IconCheckCircle, to: '/visitors/checkin' }, - { key: 'leads', label: '리드', Icon: IconExhibitors, to: '/leads' }, - { key: 'campaigns', label: '마케팅', Icon: IconBell, to: '/campaigns' }, - { key: 'sponsorship', label: '스폰서십', Icon: IconSettlement, to: '/sponsorship' }, - { key: 'cms', label: '콘텐츠 CMS', Icon: IconDocument, to: '/cms' }, -]; +/** hallLabel("제2전시장 홀7"·"홀 10" 등) → 홀 id("H7"). 파싱 불가 시 기본 H7. */ +function hallIdFromLabel(label: string | null | undefined): string { + const m = /홀\s*(\d+)/.exec(label ?? ''); + return m ? `H${m[1]}` : 'H7'; +} -/** §5B 공통 업무 기능(SCR-39~48) — 전 역할 공통 영역. */ -const WORK_NAV: { key: string; label: string; Icon: ComponentType; to: string }[] = [ - { key: 'worklog', label: '업무일지', Icon: IconDocument, to: '/work/worklog' }, - { key: 'work-schedule', label: '일정', Icon: IconCalendar, to: '/work/schedule' }, - { key: 'message', label: '쪽지', Icon: IconUsers, to: '/work/message' }, - { key: 'notice', label: '공지', Icon: IconBell, to: '/work/notice' }, - { key: 'meeting', label: '회의록', Icon: IconOperations, to: '/work/meeting' }, - { key: 'report', label: '업무보고', Icon: IconAnalytics, to: '/work/report' }, - { key: 'opinion', label: '의견접수', Icon: IconCheckCircle, to: '/work/opinion' }, - { key: 'search', label: '통합검색', Icon: IconSearch, to: '/work/search' }, -]; +/** 현재 경로가 속한 대분류 그룹 id(활성 그룹 자동 펼침용). 정적 to 항목만 매칭. */ +function activeGroupId(pathname: string): string | null { + for (const g of GROUPS) { + for (const it of g.items) { + if (it.to && (pathname === it.to || pathname.startsWith(`${it.to}/`))) return g.id; + } + } + return null; +} /** - * 웹 인증 셸 (design.md §2-2) — 좌측 240px 사이드바 + 상단 바(브레드크럼·D-데이·알림). - * 캔버스 화면은 이 셸 안에서 전폭을 사용한다. + * 웹 인증 셸 (design.md §2-2 · WISE AppLayout 구조 이식) — + * 좌측 사이드바(브랜드 로고 + 그룹 아코디언 + 하단 사용자) + 상단 바(햄버거·브레드크럼·D-데이·알림). + * 사이드바는 nav-collapsed 토글로 접힘(데스크톱 숨김 / <1024px 오버레이 드로어 + 백드롭). */ export function AppShell() { const user = useAuthStore((s) => s.user); @@ -106,44 +223,75 @@ export function AppShell() { const logout = useAuthStore((s) => s.logout); const themeResolved = useThemeStore((s) => s.resolved); const toggleTheme = useThemeStore((s) => s.toggle); + const navCollapsed = useUiStore((s) => s.navCollapsed); + const toggleNav = useUiStore((s) => s.toggleNav); + const setNavCollapsed = useUiStore((s) => s.setNavCollapsed); const navigate = useNavigate(); const location = useLocation(); const openTab = useMdiStore((s) => s.openTab); const resolvedEventId = useResolvedEventId(); + const isAdmin = useIsAdmin(); const isDark = themeResolved === 'dark'; + const { t } = useTranslation(); + + /** 메뉴 라벨 해소 — shell.menu.* i18n(4개 언어), 미해소 시 ko 폴백(label). */ + const navLabel = (labelKey: string | undefined, fallback: string) => + labelKey ? t(labelKey, { defaultValue: fallback }) : fallback; + + // 단일-열림 아코디언(소유자 지시 ②) — 한 번에 대분류 하나만 펼침. WISE LeftNav 동작 그대로. + const [openGroup, setOpenGroup] = useState(() => activeGroupId(location.pathname)); /** - * 라우트 → MDI 탭 동기화(§2.7): 셸 안의 모든 라우트 진입(네비 클릭·화면 내 링크·딥링크)이 - * 문서 탭을 열거나 활성 전환한다. openTab 은 dedup(중복 경로면 활성만) + 상한 관리를 담당한다. - * navigate 는 여기서 호출하지 않는다(탭 상호작용·네비가 이미 라우팅을 트리거) → 루프 없음. + * 라우트 → MDI 탭 동기화(§2.7) + 활성 그룹 자동 펼침. + * 화면 이동 시 활성 대분류를 펼친다(라우트=단일 출처). 비메뉴 경로는 현 상태 유지. */ useEffect(() => { openTab(location.pathname, labelForPath(location.pathname)); + const active = activeGroupId(location.pathname); + if (active) setOpenGroup(active); }, [location.pathname, openTab]); - /** 행사 스코프 항목 진입 — 대상 행사 해소 시 계산 경로로, 미해소 시 행사 선택(/login)으로. */ + const toggleGroup = (id: string) => setOpenGroup((prev) => (prev === id ? null : id)); + + /** 링크 이동 시 모바일이면 드로어 닫기(WISE maybeCloseOnMobile). */ + const closeOnMobile = () => { + if (isMobileViewport()) setNavCollapsed(true); + }; + + /** + * 행사 스코프 항목 진입 — 대상 행사 해소 시 계산 경로로. + * 참여 행사가 없으면 홈(워크스페이스 섹션·초대 안내)으로 보낸다 — 인증 사용자를 /login 으로 되돌리지 않는다(2026-07-12 소유자 링크 오류 지적). + */ function goScoped(key: string) { const build = EVENT_SCOPED_PATH[key]; if (resolvedEventId && build) { - navigate(build(resolvedEventId)); + const ws = useAuthStore.getState().workspaces.find((w) => w.eventId === resolvedEventId); + navigate(build(resolvedEventId, hallIdFromLabel(ws?.hallLabel))); } else { - navigate('/login'); // 참여 행사 없음 → 워크스페이스 선택 그리드 + navigate('/home'); } + closeOnMobile(); } + const visibleGroups = GROUPS.filter((g) => !g.admin || isAdmin); + return ( -
+
본문 바로가기 +
+ ); + })} +
+ {/* 하단 사용자 영역 — 반응형 재정렬(소유자 지적 3): 프로필 행 + 액션 아이콘 행. */}
- - - - +
+ + + +
+ {/* 모바일 드로어 백드롭 — nav 열림 시에만(데스크톱은 CSS 로 미표시). */} + {!navCollapsed && ( +
setNavCollapsed(true)} + aria-hidden="true" + /> + )} +
-
- {workspace?.eventName ?? '워크스페이스'} - / - 플로어플랜 스튜디오 +
+ +
+ {workspace?.eventName ?? '워크스페이스'} + / + {labelForPath(location.pathname)} +
{workspace && } @@ -268,7 +460,7 @@ export function AppShell() { - {/* 전 셸 화면 공통 하단 상태바 (design.md §2-2, 약 36px) */} + {/* 전 셸 화면 공통 하단 상태바 (design.md §2-2) */}
diff --git a/src/frontend/src/components/layout/app-shell.css b/src/frontend/src/components/layout/app-shell.css index 69de0ca..a4d87c4 100644 --- a/src/frontend/src/components/layout/app-shell.css +++ b/src/frontend/src/components/layout/app-shell.css @@ -1,9 +1,11 @@ +/* ══════════ 웹 인증 셸 (WISE AppLayout 구조 이식) ══════════ */ .kx-shell { display: flex; height: 100vh; overflow: hidden; } +/* ── 사이드바 ── */ .kx-shell__sidebar { width: var(--sidebar-w); flex-shrink: 0; @@ -11,43 +13,49 @@ border-right: var(--border-card); display: flex; flex-direction: column; - padding: var(--space-5) 0; + min-height: 0; + transition: width 0.2s ease; +} +/* 데스크톱 접힘 — 사이드바 숨김(콘텐츠 전폭). */ +.kx-shell.is-nav-collapsed .kx-shell__sidebar { + width: 0; + overflow: hidden; + border-right: none; } +/* 브랜드 — 실제 KINTEX CI 워드마크. 다크 모드 대비 화이트 플레이트(JPG 는 알파 없음). */ .kx-shell__brand { display: flex; align-items: center; gap: var(--space-3); - padding: 0 var(--space-5); - margin-bottom: var(--space-5); + height: 56px; + flex: none; + padding: 0 var(--space-4); + border-bottom: var(--border-card); + text-decoration: none; + overflow: hidden; } -.kx-shell__brand-mark { - width: 32px; - height: 32px; +.kx-shell__brand-logo { + height: 22px; + width: auto; + flex: none; + background: #fff; + padding: 3px 7px; border-radius: var(--radius-sm); - background: var(--color-primary-600); - color: var(--color-white); - display: flex; - align-items: center; - justify-content: center; - font-weight: 700; + display: block; } -.kx-shell__brand-text { - display: flex; - flex-direction: column; - font-size: var(--fs-h3); - font-weight: 700; - color: var(--color-primary-700); - line-height: 1.1; -} -.kx-shell__brand-text small { +.kx-shell__brand-sub { font-size: 11px; - font-weight: 500; + font-weight: 600; color: var(--color-neutral-500); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } +/* 행사 스위처 */ .kx-shell__event-switch { - margin: 0 var(--space-4) var(--space-5); + margin: var(--space-3) var(--space-3) 0; padding: var(--space-3); background: var(--color-neutral-050); border: var(--border-card); @@ -56,17 +64,32 @@ display: flex; flex-direction: column; gap: 2px; + flex: none; } .kx-shell__event-name { font-size: var(--fs-body); font-weight: 600; color: var(--color-neutral-900); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .kx-shell__event-meta { font-size: var(--fs-caption); color: var(--color-neutral-500); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } +/* 메뉴 스크롤 영역 — 사이드바 중앙(하단 사용자 고정). */ +.kx-shell__nav-scroll { + flex: 1 1 auto; + min-height: 0; + overflow-y: auto; + overflow-x: hidden; + padding: var(--space-3) 0 var(--space-4); +} .kx-shell__nav { list-style: none; margin: 0; @@ -74,17 +97,78 @@ display: flex; flex-direction: column; gap: 2px; - flex: 1; } +.kx-shell__nav--sub { + padding: 2px 0 var(--space-2); +} +/* 소그룹 구분 헤더(시스템관리 20항목 정리) — 클릭 불가, WISE 구분선 라벨. */ +.kx-shell__nav-section { + margin: var(--space-2) 0 2px; + padding: 4px var(--space-4) 3px; + font-size: 10px; + font-weight: 700; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--color-neutral-500); + border-top: 1px solid var(--color-neutral-100); +} +.kx-shell__nav-section:first-child { + margin-top: 0; + border-top: none; +} + +/* 대분류 그룹(아코디언) */ +.kx-shell__group { + padding: 0 var(--space-3); +} +.kx-shell__group-title { + display: flex; + align-items: center; + gap: var(--space-3); + width: 100%; + padding: 9px var(--space-4); + border: none; + background: transparent; + border-radius: var(--radius-sm); + color: var(--color-neutral-700); + font-size: var(--fs-body); + font-weight: 600; + text-align: left; + transition: background 0.15s ease, color 0.15s ease; +} +.kx-shell__group-title:hover { + background: var(--color-neutral-050); + color: var(--color-neutral-900); +} +.kx-shell__group-label { + flex: 1 1 auto; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.kx-shell__group-caret { + flex: none; + color: var(--color-neutral-500); + transition: transform 0.2s ease; +} +.kx-shell__group-caret.is-open { + transform: rotate(180deg); +} + +/* 링크 */ .kx-shell__nav-link { display: flex; align-items: center; gap: var(--space-3); - padding: 10px var(--space-4); + width: 100%; + padding: 8px var(--space-4); border-radius: var(--radius-sm); color: var(--color-neutral-700); font-size: var(--fs-body); font-weight: 500; + text-decoration: none; + transition: background 0.15s ease, color 0.15s ease; } .kx-shell__nav-link:hover { background: var(--color-neutral-050); @@ -95,9 +179,11 @@ color: var(--color-primary-700); font-weight: 600; } -/* 행사 스코프 진입(대시보드·플로어플랜·참가업체) — button 이지만 nav-link 와 동일 표현. */ +.kx-shell__nav-link--top { + font-weight: 600; +} +/* 스코프 진입(button) — nav-link 와 동일 표현. */ .kx-shell__nav-link--btn { - width: 100%; border: 0; background: transparent; text-align: left; @@ -105,99 +191,114 @@ font-family: inherit; } .kx-shell__nav-icon { - width: 20px; + width: 18px; + flex: none; display: inline-flex; align-items: center; justify-content: center; + color: var(--color-neutral-500); +} +.kx-shell__nav-link.is-active .kx-shell__nav-icon { + color: var(--color-primary-700); +} +/* 하위 링크 앞 점 마커(들여쓰기 정렬) */ +.kx-shell__nav-dot { + width: 5px; + height: 5px; + margin-left: 6px; + border-radius: 50%; + background: currentColor; + opacity: 0.4; + flex: none; +} +.kx-shell__nav-link.is-active .kx-shell__nav-dot { + opacity: 1; + background: var(--color-primary-600); } +/* ── 하단 사용자 영역 (반응형 재정렬) ── */ .kx-shell__user { + flex: none; + border-top: var(--border-card); + padding: var(--space-3) var(--space-3) var(--space-4); + display: flex; + flex-direction: column; + gap: var(--space-2); +} +.kx-shell__user-profile { display: flex; align-items: center; gap: var(--space-2); - padding: var(--space-4) var(--space-5) 0; - border-top: var(--border-card); - margin-top: var(--space-3); + width: 100%; + min-width: 0; + border: none; + background: transparent; + padding: 6px var(--space-2); + border-radius: var(--radius-sm); + text-align: left; + cursor: pointer; +} +.kx-shell__user-profile:hover { + background: var(--color-neutral-050); } .kx-shell__avatar { - width: 28px; - height: 28px; + width: 30px; + height: 30px; + flex: none; border-radius: 50%; background: var(--color-primary-100); color: var(--color-primary-700); - display: flex; + display: inline-flex; align-items: center; justify-content: center; font-weight: 600; font-size: 13px; } .kx-shell__user-name { - flex: 1; - font-size: var(--fs-caption); - font-weight: 500; - color: var(--color-neutral-700); + flex: 1 1 auto; + min-width: 0; + font-size: var(--fs-body); + font-weight: 600; + color: var(--color-neutral-900); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } -.kx-shell__theme-toggle { - width: 28px; - height: 28px; - flex-shrink: 0; - border-radius: 50%; - border: var(--border-card); - background: var(--color-neutral-050); +.kx-shell__user-actions { + display: flex; + align-items: center; + gap: var(--space-1); +} +.kx-shell__user-action { + width: 34px; + height: 34px; + flex: none; + border: none; + border-radius: var(--radius-sm); + background: transparent; color: var(--color-neutral-500); display: inline-flex; align-items: center; justify-content: center; - cursor: pointer; + transition: background 0.15s ease, color 0.15s ease; } -.kx-shell__theme-toggle:hover { - color: var(--color-primary-600); - background: var(--color-neutral-100); -} - -.kx-shell__logout { - background: none; - border: none; - font-size: var(--fs-caption); - color: var(--color-neutral-500); -} -.kx-shell__logout:hover { +.kx-shell__user-action:hover { + background: var(--color-neutral-050); color: var(--color-primary-600); } - -/* §5B 업무 공통 2번째 내비 그룹 — 콘텐츠 높이만 차지, 사이드바 스크롤. */ -.kx-shell__sidebar { - overflow-y: auto; -} -.kx-shell__nav { - flex: 0 0 auto; -} -.kx-shell__nav-label { - padding: var(--space-4) var(--space-5) var(--space-2); - font-size: 11px; - font-weight: 700; - letter-spacing: 0.04em; - color: var(--color-neutral-500); - text-transform: uppercase; -} -.kx-shell__user { - margin-top: auto; -} -.kx-shell__avatar--btn { - border: none; - cursor: pointer; -} -.kx-shell__user-name--btn { - background: none; - border: none; - text-align: left; - cursor: pointer; - padding: 0; -} -.kx-shell__user-name--btn:hover { - color: var(--color-primary-600); +/* 언어 셀렉트 — 액션 행에서 가운데 신축(줄바꿈/오버플로 방지). */ +.kx-shell__user-lang { + flex: 1 1 auto; + justify-content: center; + overflow: hidden; } +/* ── 모바일 드로어 백드롭(데스크톱 미표시) ── */ +.kx-shell__backdrop { + display: none; +} + +/* ══════════ 메인 컬럼 ══════════ */ .kx-shell__main { flex: 1; display: flex; @@ -212,22 +313,63 @@ display: flex; align-items: center; justify-content: space-between; + gap: var(--space-4); padding: 0 var(--gutter); } +.kx-shell__topbar-left { + display: flex; + align-items: center; + gap: var(--space-2); + flex: 1 1 auto; + min-width: 0; +} +.kx-shell__nav-toggle { + width: 38px; + height: 38px; + flex: none; + border: 1px solid transparent; + border-radius: var(--radius-sm); + background: transparent; + color: var(--color-neutral-500); + display: inline-flex; + align-items: center; + justify-content: center; + transition: background 0.15s ease, color 0.15s ease; +} +.kx-shell__nav-toggle:hover { + background: var(--color-neutral-100); + color: var(--color-neutral-900); +} .kx-shell__crumb { font-size: var(--fs-body); color: var(--color-neutral-500); display: flex; align-items: center; gap: var(--space-2); + min-width: 0; +} +.kx-shell__crumb-root { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 200px; } .kx-shell__crumb-sep { color: var(--color-neutral-200); + flex: none; +} +.kx-shell__crumb-cur { + color: var(--color-neutral-900); + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .kx-shell__topbar-right { display: flex; align-items: center; gap: var(--space-3); + flex: none; } .kx-shell__icon-btn { width: 32px; @@ -251,7 +393,7 @@ display: flex; } -/* ── 하단 상태바/푸터 (design.md §2-2, 약 36px) — 사이드바 우측 전폭·콘텐츠 아래 고정 ── */ +/* ── 하단 상태바/푸터 (design.md §2-2, 약 36px) ── */ .kx-shell__footer { flex-shrink: 0; height: 36px; @@ -337,7 +479,6 @@ .kx-mdi__tab:hover { background: var(--color-neutral-100); } -/* 활성 탭 — 흰 서피스 + 상단 2px primary 인디케이터(§2.7-2). */ .kx-mdi__tab.is-active { background: var(--color-white); border-color: var(--color-neutral-200); @@ -384,9 +525,48 @@ color: var(--color-neutral-900); } +/* ══════════ 반응형 ══════════ */ +/* <1024px — 사이드바를 오버레이 드로어로. 접힘 시 화면 밖으로 슬라이드. */ +@media (max-width: 1024px) { + .kx-shell__sidebar { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: var(--sidebar-w); + z-index: 40; + box-shadow: var(--shadow-level2); + transform: translateX(0); + transition: transform 0.2s ease; + } + .kx-shell.is-nav-collapsed .kx-shell__sidebar { + width: var(--sidebar-w); + overflow: hidden; + border-right: var(--border-card); + transform: translateX(-100%); + } + .kx-shell__backdrop { + display: block; + position: fixed; + inset: 0; + background: rgba(8, 14, 24, 0.5); + z-index: 35; + } +} + /* 모바일 폭에서는 탭 스트립 숨김(단일 화면 포커스 — §2.7-6). */ @media (max-width: 720px) { .kx-mdi { display: none; } } + +@media (max-width: 640px) { + .kx-shell__crumb-root, + .kx-shell__crumb-sep { + display: none; + } + .kx-shell__topbar { + padding: 0 var(--space-4); + } +} diff --git a/src/frontend/src/components/ui/icons.tsx b/src/frontend/src/components/ui/icons.tsx index dbe9062..d17f308 100644 --- a/src/frontend/src/components/ui/icons.tsx +++ b/src/frontend/src/components/ui/icons.tsx @@ -468,6 +468,27 @@ export function IconMoon(p: IconProps) { ); } +/** ⎋ 로그아웃(문 + 화살표). */ +export function IconLogOut(p: IconProps) { + return ( + + + + + + ); +} + +/** ○ 사용자(마이페이지 아바타 폴백). */ +export function IconUser(p: IconProps) { + return ( + + + + + ); +} + /** ● 오프라인(연결 끊김). */ export function IconWifiOff(p: IconProps) { return ( diff --git a/src/frontend/src/i18n/locales/en.json b/src/frontend/src/i18n/locales/en.json index 336f1de..d4fb81f 100644 --- a/src/frontend/src/i18n/locales/en.json +++ b/src/frontend/src/i18n/locales/en.json @@ -31,6 +31,75 @@ "select": "Select language" }, "shell": { + "menu": { + "home": "Home", + "groups": { + "ops": "Exhibition Ops", + "design": "Design & Build", + "visitor": "Visitors & Marketing", + "finance": "Settlement & Analytics", + "work": "Workspace", + "system": "System Admin" + }, + "items": { + "dashboard": "Dashboard", + "exhibitors": "Exhibitors", + "schedule": "Schedule", + "halls": "Hall Assignment", + "boothSales": "Booth Sales", + "operations": "Onsite Ops", + "floorplan": "Floorplan Studio", + "documents": "Docs & Milestones", + "auctions": "Construction Auction", + "contractor": "Contractor Booths", + "logistics": "Move In/Out", + "visitors": "Visitors", + "checkin": "Check-in Desk", + "leads": "Leads", + "campaigns": "Marketing", + "sponsorship": "Sponsorship", + "cms": "Content CMS", + "settlement": "Settlement", + "analytics": "Analytics", + "worklog": "Work Log", + "workSchedule": "Schedule", + "message": "Messages", + "notice": "Notices", + "meeting": "Meetings", + "report": "Reports", + "approval": "Approvals", + "opinion": "Feedback", + "search": "Search", + "appqr": "Mobile App", + "admin": "Admin Dashboard", + "users": "Users", + "roles": "Roles & Permissions", + "depts": "Departments", + "companies": "Companies", + "menus": "Menus", + "programs": "Programs", + "roleMenus": "Role-Menu Mapping", + "codes": "Common Codes", + "authPolicy": "Auth Policy", + "loginHistory": "Login History", + "audit": "Audit Log", + "errorLog": "Error Log", + "systemHealth": "System Health", + "settings": "System Settings", + "mailConfig": "Mail Config", + "notifyConfig": "Notify Config", + "tenants": "Tenants", + "rulesets": "Rulesets", + "slides": "Login Slides" + }, + "sections": { + "userOrg": "Users & Org", + "menuAuth": "Menus & Codes", + "policyLog": "Policy & Logs", + "statusConfig": "Status & Config", + "masterEtc": "Master & Others" + } + }, "nav": { "events": "Events", "exhibit": "Exhibitors", diff --git a/src/frontend/src/i18n/locales/ja.json b/src/frontend/src/i18n/locales/ja.json index bbbfdb7..422d671 100644 --- a/src/frontend/src/i18n/locales/ja.json +++ b/src/frontend/src/i18n/locales/ja.json @@ -31,6 +31,75 @@ "select": "言語を選択" }, "shell": { + "menu": { + "home": "ホーム", + "groups": { + "ops": "展示運営", + "design": "設計・施工", + "visitor": "来場者・マーケティング", + "finance": "精算・分析", + "work": "業務共通", + "system": "システム管理" + }, + "items": { + "dashboard": "ダッシュボード", + "exhibitors": "出展社管理", + "schedule": "展示日程", + "halls": "ホール割当", + "boothSales": "ブース販売", + "operations": "現場運営", + "floorplan": "フロアプランスタジオ", + "documents": "書類・マイルストーン", + "auctions": "工事オークション", + "contractor": "受注ブース", + "logistics": "搬入・搬出", + "visitors": "来場者", + "checkin": "チェックインデスク", + "leads": "リード", + "campaigns": "マーケティング", + "sponsorship": "スポンサーシップ", + "cms": "コンテンツCMS", + "settlement": "精算", + "analytics": "経営分析", + "worklog": "業務日誌", + "workSchedule": "日程", + "message": "メッセージ", + "notice": "お知らせ", + "meeting": "議事録", + "report": "業務報告", + "approval": "決裁", + "opinion": "意見受付", + "search": "統合検索", + "appqr": "モバイルアプリ", + "admin": "管理ダッシュボード", + "users": "ユーザー管理", + "roles": "役割/権限", + "depts": "組織管理", + "companies": "会社管理", + "menus": "メニュー管理", + "programs": "プログラム管理", + "roleMenus": "役割-メニュー割当", + "codes": "共通コード", + "authPolicy": "認証ポリシー", + "loginHistory": "ログイン履歴", + "audit": "監査ログ", + "errorLog": "エラーログ", + "systemHealth": "システム状態", + "settings": "システム設定", + "mailConfig": "メール設定", + "notifyConfig": "通知設定", + "tenants": "テナント", + "rulesets": "ルールセット", + "slides": "ログインスライド" + }, + "sections": { + "userOrg": "ユーザー・組織", + "menuAuth": "メニュー・コード", + "policyLog": "ポリシー・ログ", + "statusConfig": "状態・設定", + "masterEtc": "マスター・その他" + } + }, "nav": { "events": "イベント", "exhibit": "出展案内", diff --git a/src/frontend/src/i18n/locales/ko.json b/src/frontend/src/i18n/locales/ko.json index e315f3f..0e4058a 100644 --- a/src/frontend/src/i18n/locales/ko.json +++ b/src/frontend/src/i18n/locales/ko.json @@ -31,6 +31,75 @@ "select": "언어 선택" }, "shell": { + "menu": { + "home": "홈", + "groups": { + "ops": "전시 운영", + "design": "설계·시공", + "visitor": "관람객·마케팅", + "finance": "정산·분석", + "work": "업무 공통", + "system": "시스템관리" + }, + "items": { + "dashboard": "대시보드", + "exhibitors": "참가업체 관리", + "schedule": "전시 일정", + "halls": "홀 배정", + "boothSales": "부스 판매", + "operations": "현장운영", + "floorplan": "플로어플랜 스튜디오", + "documents": "서류·마일스톤", + "auctions": "공사 옥션", + "contractor": "수주 부스", + "logistics": "반입·반출", + "visitors": "관람객", + "checkin": "체크인 데스크", + "leads": "리드", + "campaigns": "마케팅", + "sponsorship": "스폰서십", + "cms": "콘텐츠 CMS", + "settlement": "정산", + "analytics": "경영분석", + "worklog": "업무일지", + "workSchedule": "일정", + "message": "쪽지", + "notice": "공지", + "meeting": "회의록", + "report": "업무보고", + "approval": "결재", + "opinion": "의견접수", + "search": "통합검색", + "appqr": "모바일 앱 설치", + "admin": "관리 대시보드", + "users": "사용자 관리", + "roles": "역할/권한", + "depts": "조직 관리", + "companies": "회사 관리", + "menus": "메뉴 관리", + "programs": "프로그램 관리", + "roleMenus": "역할-메뉴 매핑", + "codes": "공통코드", + "authPolicy": "인증 정책", + "loginHistory": "로그인 이력", + "audit": "감사로그", + "errorLog": "오류 로그", + "systemHealth": "시스템 상태", + "settings": "시스템설정", + "mailConfig": "메일 설정", + "notifyConfig": "알림 설정", + "tenants": "테넌트", + "rulesets": "룰셋", + "slides": "로그인 슬라이드" + }, + "sections": { + "userOrg": "사용자·조직", + "menuAuth": "메뉴·프로그램·코드", + "policyLog": "정책·이력·로그", + "statusConfig": "상태·설정", + "masterEtc": "마스터·기타" + } + }, "nav": { "events": "행사", "exhibit": "참가안내", diff --git a/src/frontend/src/i18n/locales/zh.json b/src/frontend/src/i18n/locales/zh.json index a2408bc..d5f43c9 100644 --- a/src/frontend/src/i18n/locales/zh.json +++ b/src/frontend/src/i18n/locales/zh.json @@ -31,6 +31,75 @@ "select": "选择语言" }, "shell": { + "menu": { + "home": "首页", + "groups": { + "ops": "展会运营", + "design": "设计·施工", + "visitor": "观众·营销", + "finance": "结算·分析", + "work": "通用业务", + "system": "系统管理" + }, + "items": { + "dashboard": "仪表板", + "exhibitors": "参展商管理", + "schedule": "展会日程", + "halls": "展厅分配", + "boothSales": "展位销售", + "operations": "现场运营", + "floorplan": "平面图工作室", + "documents": "文件·里程碑", + "auctions": "施工竞标", + "contractor": "中标展位", + "logistics": "进场·退场", + "visitors": "观众", + "checkin": "签到台", + "leads": "潜在客户", + "campaigns": "营销", + "sponsorship": "赞助", + "cms": "内容CMS", + "settlement": "结算", + "analytics": "经营分析", + "worklog": "工作日志", + "workSchedule": "日程", + "message": "便签", + "notice": "公告", + "meeting": "会议记录", + "report": "工作报告", + "approval": "审批", + "opinion": "意见收集", + "search": "综合搜索", + "appqr": "移动应用安装", + "admin": "管理仪表板", + "users": "用户管理", + "roles": "角色/权限", + "depts": "组织管理", + "companies": "公司管理", + "menus": "菜单管理", + "programs": "程序管理", + "roleMenus": "角色-菜单映射", + "codes": "公共代码", + "authPolicy": "认证策略", + "loginHistory": "登录历史", + "audit": "审计日志", + "errorLog": "错误日志", + "systemHealth": "系统状态", + "settings": "系统设置", + "mailConfig": "邮件设置", + "notifyConfig": "通知设置", + "tenants": "租户", + "rulesets": "规则集", + "slides": "登录幻灯片" + }, + "sections": { + "userOrg": "用户·组织", + "menuAuth": "菜单·代码", + "policyLog": "策略·日志", + "statusConfig": "状态·设置", + "masterEtc": "主数据·其他" + } + }, "nav": { "events": "展会", "exhibit": "参展指南", diff --git a/src/frontend/src/screens/admin/AuthPolicyPage.tsx b/src/frontend/src/screens/admin/AuthPolicyPage.tsx new file mode 100644 index 0000000..3d9218e --- /dev/null +++ b/src/frontend/src/screens/admin/AuthPolicyPage.tsx @@ -0,0 +1,120 @@ +/* + * W12 시스템관리 — 인증 정책(비밀번호·로그인 잠금·세션). + * 정본: GET/PUT /api/admin/auth-policy → AuthPolicy (AuthPolicyController). 서버가 범위 클램프. + * 로그인 잠금 수치는 LoginAttemptService(login.*)와 정합(관리 화면 계약). + */ +import { useEffect, useState } from 'react'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { ErrorState, Skeleton } from '../../components/ui/States'; +import { Button } from '../../components/ui/Button'; +import { errMessage, useToast } from '../work/workShared'; +import { authPolicyApi, type AuthPolicy, type AuthPolicySaveBody } from './systemBasicsApi'; +import './admin-modules.css'; + +export function AuthPolicyPage() { + const { t } = useTranslation(); + const qc = useQueryClient(); + const { show, node: toast } = useToast(); + const q = useQuery({ queryKey: ['admin-auth-policy'], queryFn: authPolicyApi.get, retry: false }); + const [form, setForm] = useState(null); + + useEffect(() => { + if (q.data) setForm(q.data); + }, [q.data]); + + const saveM = useMutation({ + mutationFn: (body: AuthPolicySaveBody) => authPolicyApi.save(body), + onSuccess: () => { + show(t('authPolicy.saved')); + qc.invalidateQueries({ queryKey: ['admin-auth-policy'] }); + }, + onError: (e) => show(errMessage(e)), + }); + + function num(key: keyof AuthPolicy, v: string) { + setForm((f) => (f ? { ...f, [key]: Number(v) } : f)); + } + function yn(key: keyof AuthPolicy, checked: boolean) { + setForm((f) => (f ? { ...f, [key]: checked ? 'Y' : 'N' } : f)); + } + function submit(e: React.FormEvent) { + e.preventDefault(); + if (!form) return; + const { updatedAt: _a, updatedBy: _b, ...body } = form; + saveM.mutate(body); + } + + return ( +
+
+
+

{t('authPolicy.title')}

+

{t('authPolicy.subtitle')}

+
+
+ + {q.isLoading && } + {q.isError && !q.isLoading && q.refetch()} />} + + {!q.isLoading && !q.isError && form && ( +
+

{t('authPolicy.pwSection')}

+
+ + + + + +
+ +

{t('authPolicy.lockSection')}

+
+ + + +
+ +
+ +
+
+ )} + {toast} +
+ ); +} diff --git a/src/frontend/src/screens/admin/CompanyAdminPage.tsx b/src/frontend/src/screens/admin/CompanyAdminPage.tsx new file mode 100644 index 0000000..f937db1 --- /dev/null +++ b/src/frontend/src/screens/admin/CompanyAdminPage.tsx @@ -0,0 +1,232 @@ +/* + * W12 시스템관리 — 회사(거래처) 관리. + * 정본: GET/POST /api/admin/companies · DELETE /{id} (CompanyController). 목록 PageResponse, 연락처 마스킹. + * 보안: 목록의 contactTel 은 마스킹되어 도착. 수정 시 마스킹된 값을 다시 전송하면 마스킹이 저장되므로 + * 전화 필드는 편집 시 공란 시작(미입력=미변경 아님 → 명시적으로 다시 입력) — 화면 안내. + */ +import { useState } from 'react'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States'; +import { Button } from '../../components/ui/Button'; +import { IconPlus, IconSearch } from '../../components/ui/icons'; +import { errMessage, useToast } from '../work/workShared'; +import { companyApi, PARTNER_TYPES, type Company, type CompanySaveBody } from './systemBasicsApi'; +import { Pager } from './LoginHistoryPage'; +import './admin-modules.css'; + +export function CompanyAdminPage() { + const { t } = useTranslation(); + const qc = useQueryClient(); + const { show, node: toast } = useToast(); + const [keyword, setKeyword] = useState(''); + const [partnerType, setPartnerType] = useState(''); + const [applied, setApplied] = useState<{ keyword: string; partnerType: string }>({ keyword: '', partnerType: '' }); + const [page, setPage] = useState(0); + const size = 20; + const [editing, setEditing] = useState(undefined); + + const q = useQuery({ + queryKey: ['admin-companies', applied, page], + queryFn: () => companyApi.list({ ...applied, page, size }), + retry: false, + }); + const rows = q.data?.items ?? []; + const total = q.data?.total ?? 0; + const totalPages = Math.max(1, Math.ceil(total / size)); + + const saveM = useMutation({ + mutationFn: (body: CompanySaveBody) => companyApi.save(body), + onSuccess: () => { show(t('company.saved')); setEditing(undefined); qc.invalidateQueries({ queryKey: ['admin-companies'] }); }, + onError: (e) => show(errMessage(e)), + }); + const delM = useMutation({ + mutationFn: (id: string) => companyApi.remove(id), + onSuccess: () => { show(t('company.deleted')); qc.invalidateQueries({ queryKey: ['admin-companies'] }); }, + onError: (e) => show(errMessage(e)), + }); + + function apply() { setPage(0); setApplied({ keyword, partnerType }); } + + return ( +
+
+
+

{t('company.title')}

+

{t('company.subtitle')}

+
+ +
+ +
+
+ + +
+ +
+
+
+ + {q.isLoading && } + {q.isError && !q.isLoading && q.refetch()} />} + + {!q.isLoading && !q.isError && ( +
+ {rows.length === 0 ? ( + + ) : ( + <> +
+ + + + + + + + + + + + + {rows.map((r) => ( + + + + + + + + + + ))} + +
{t('company.colName')}{t('company.colBizNo')}{t('company.colType')}{t('company.colContact')}{t('company.colTel')}{t('company.colUse')} +
{r.companyName}{r.bizNo ?? '-'}{r.partnerType ? t(`company.pt_${r.partnerType}`) : '-'}{r.contactName ?? '-'}{r.contactTel ?? '-'}{r.useYn === 'N' ? t('sysadmin.noUse') : t('sysadmin.use')} + + +
+
+ setPage((p) => Math.max(0, p - 1))} + onNext={() => setPage((p) => Math.min(totalPages - 1, p + 1))} /> + + )} +
+ )} + + {editing !== undefined && ( + setEditing(undefined)} onSubmit={(b) => saveM.mutate(b)} /> + )} + {toast} +
+ ); +} + +function CompanyModal({ company, saving, onClose, onSubmit }: { + company: Company | null; saving: boolean; onClose: () => void; onSubmit: (b: CompanySaveBody) => void; +}) { + const { t } = useTranslation(); + const isNew = company === null; + const [companyName, setName] = useState(company?.companyName ?? ''); + const [bizNo, setBizNo] = useState(company?.bizNo ?? ''); + const [ceoName, setCeo] = useState(company?.ceoName ?? ''); + const [bizType, setBizType] = useState(company?.bizType ?? ''); + const [contactName, setContact] = useState(company?.contactName ?? ''); + const [contactTel, setTel] = useState(''); // 마스킹 방지: 편집 시 공란 시작 + const [address, setAddress] = useState(company?.address ?? ''); + const [partnerType, setPartner] = useState(company?.partnerType ?? ''); + const [useYn, setUseYn] = useState(company?.useYn ?? 'Y'); + const [error, setError] = useState(null); + + function submit(e: React.FormEvent) { + e.preventDefault(); + if (!companyName.trim()) { setError(t('company.errRequired')); return; } + onSubmit({ + id: company?.id ?? null, + companyName: companyName.trim(), + bizNo: bizNo.trim() || null, + ceoName: ceoName.trim() || null, + bizType: bizType.trim() || null, + contactName: contactName.trim() || null, + contactTel: contactTel.trim() || null, + address: address.trim() || null, + partnerType: partnerType || null, + useYn, + }); + } + + return ( +
+
+
+

{isNew ? t('company.add') : t('company.edit')}

+
+ + + + + + + + + +
+ {!isNew &&

{t('company.telMaskNote')}

} + {error &&

{error}

} +
+ + +
+
+
+ ); +} diff --git a/src/frontend/src/screens/admin/DeptAdminPage.tsx b/src/frontend/src/screens/admin/DeptAdminPage.tsx new file mode 100644 index 0000000..00a3c41 --- /dev/null +++ b/src/frontend/src/screens/admin/DeptAdminPage.tsx @@ -0,0 +1,150 @@ +/* + * W12 시스템관리 — 조직(부서 트리) 관리. + * 정본: GET/POST /api/admin/depts · DELETE /{id} (DeptController). 트리 응답(children 중첩), upsert 저장. + */ +import { useMemo, useState } from 'react'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States'; +import { Button } from '../../components/ui/Button'; +import { IconPlus } from '../../components/ui/icons'; +import { errMessage, useToast } from '../work/workShared'; +import { deptApi, type DeptNode, type DeptSaveBody } from './systemBasicsApi'; +import './admin-modules.css'; + +interface FlatDept { node: DeptNode; depth: number } + +function flatten(nodes: DeptNode[], depth: number, out: FlatDept[]) { + for (const n of nodes) { + out.push({ node: n, depth }); + if (n.children && n.children.length) flatten(n.children, depth + 1, out); + } +} + +export function DeptAdminPage() { + const { t } = useTranslation(); + const qc = useQueryClient(); + const { show, node: toast } = useToast(); + const q = useQuery({ queryKey: ['admin-depts'], queryFn: deptApi.tree, retry: false }); + const [editing, setEditing] = useState<{ node: DeptNode | null; parentId: string | null } | undefined>(undefined); + + const tree = q.data ?? []; + const flat = useMemo(() => { const o: FlatDept[] = []; flatten(tree, 0, o); return o; }, [tree]); + + const saveM = useMutation({ + mutationFn: (body: DeptSaveBody) => deptApi.save(body), + onSuccess: () => { show(t('dept.saved')); setEditing(undefined); qc.invalidateQueries({ queryKey: ['admin-depts'] }); }, + onError: (e) => show(errMessage(e)), + }); + const delM = useMutation({ + mutationFn: (id: string) => deptApi.remove(id), + onSuccess: () => { show(t('dept.deleted')); qc.invalidateQueries({ queryKey: ['admin-depts'] }); }, + onError: (e) => show(errMessage(e)), + }); + + return ( +
+
+
+

{t('dept.title')}

+

{t('dept.subtitle')}

+
+ +
+ + {q.isLoading && } + {q.isError && !q.isLoading && q.refetch()} />} + + {!q.isLoading && !q.isError && ( +
+ {flat.length === 0 ? ( + + ) : ( +
    + {flat.map(({ node, depth }) => ( +
  • + + {node.deptName} + {node.useYn === 'N' && · {t('sysadmin.noUse')}} + + + + + + +
  • + ))} +
+ )} +
+ )} + + {editing !== undefined && ( + setEditing(undefined)} onSubmit={(b) => saveM.mutate(b)} /> + )} + {toast} +
+ ); +} + +function DeptModal({ node, parentId, saving, onClose, onSubmit }: { + node: DeptNode | null; parentId: string | null; saving: boolean; + onClose: () => void; onSubmit: (b: DeptSaveBody) => void; +}) { + const { t } = useTranslation(); + const isNew = node === null; + const [deptName, setName] = useState(node?.deptName ?? ''); + const [sortOrder, setSort] = useState(node?.sortOrder ?? 0); + const [useYn, setUseYn] = useState(node?.useYn ?? 'Y'); + const [error, setError] = useState(null); + + function submit(e: React.FormEvent) { + e.preventDefault(); + if (!deptName.trim()) { setError(t('dept.errRequired')); return; } + onSubmit({ + id: node?.id ?? null, + deptName: deptName.trim(), + parentId: node ? node.parentId : parentId, + sortOrder, + useYn, + }); + } + + return ( +
+
+
+

{isNew ? t('dept.add') : t('dept.edit')}

+
+ + + +
+ {error &&

{error}

} +
+ + +
+
+
+ ); +} diff --git a/src/frontend/src/screens/admin/ErrorLogPage.tsx b/src/frontend/src/screens/admin/ErrorLogPage.tsx new file mode 100644 index 0000000..25c0a5c --- /dev/null +++ b/src/frontend/src/screens/admin/ErrorLogPage.tsx @@ -0,0 +1,98 @@ +/* + * W12 시스템관리 — 오류 로그 조회 (읽기전용). + * 정본: GET /api/admin/error-log?errorCode&page&size → PageResponse (ErrorLogController). + * 보안: summary 는 백엔드에서 요약 1줄로만 저장/전달(스택트레이스·민감정보 제외, §0-3). + */ +import { useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States'; +import { Button } from '../../components/ui/Button'; +import { IconSearch } from '../../components/ui/icons'; +import { fmtDateTime } from '../work/workShared'; +import { errorLogApi } from './systemBasicsApi'; +import { Pager } from './LoginHistoryPage'; +import './admin-modules.css'; + +export function ErrorLogPage() { + const { t } = useTranslation(); + const [errorCode, setErrorCode] = useState(''); + const [applied, setApplied] = useState(''); + const [page, setPage] = useState(0); + const size = 20; + + const q = useQuery({ + queryKey: ['admin-error-log', applied, page], + queryFn: () => errorLogApi.list(applied, page, size), + retry: false, + }); + const rows = q.data?.items ?? []; + const total = q.data?.total ?? 0; + const totalPages = Math.max(1, Math.ceil(total / size)); + + return ( +
+
+
+

{t('errorLog.title')}

+

{t('errorLog.subtitle')}

+
+
+ +
+
+ +
+ +
+
+
+ + {q.isLoading && } + {q.isError && !q.isLoading && q.refetch()} />} + + {!q.isLoading && !q.isError && ( +
+ {rows.length === 0 ? ( + + ) : ( + <> +
+ + + + + + + + + + + + {rows.map((r) => ( + + + + + + + + ))} + +
{t('errorLog.colTime')}{t('errorLog.colCode')}{t('errorLog.colMethod')}{t('errorLog.colPath')}{t('errorLog.colSummary')}
{fmtDateTime(r.createdAt)}{r.errorCode ?? '-'}{r.method ?? '-'}{r.path ?? '-'}{r.summary ?? '-'}
+
+ setPage((p) => Math.max(0, p - 1))} + onNext={() => setPage((p) => Math.min(totalPages - 1, p + 1))} /> + + )} +
+ )} +
+ ); +} diff --git a/src/frontend/src/screens/admin/InfraConfigPage.tsx b/src/frontend/src/screens/admin/InfraConfigPage.tsx new file mode 100644 index 0000000..66d504c --- /dev/null +++ b/src/frontend/src/screens/admin/InfraConfigPage.tsx @@ -0,0 +1,115 @@ +/* + * W12 시스템관리 — 메일/알림 설정(sys_setting mail./notify. 프리픽스). + * 정본: GET/PUT /api/admin/mail-config · /api/admin/notify-config (MailConfigController/NotifyConfigController). + * 보안: secretYn='Y' 값은 마스킹(********)되어 도착 — 마스킹 그대로 저장하면 미변경 처리(원문 보존). + */ +import { useEffect, useState } from 'react'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { ErrorState, Skeleton } from '../../components/ui/States'; +import { Button } from '../../components/ui/Button'; +import { errMessage, useToast } from '../work/workShared'; +import { + CONFIG_MASK, mailConfigApi, notifyConfigApi, + type InfraConfigRow, type InfraConfigUpdateBody, +} from './systemBasicsApi'; +import './admin-modules.css'; + +type Variant = 'mail' | 'notify'; + +function InfraConfig({ variant }: { variant: Variant }) { + const { t } = useTranslation(); + const qc = useQueryClient(); + const { show, node: toast } = useToast(); + const apiObj = variant === 'mail' ? mailConfigApi : notifyConfigApi; + const titleKey = variant === 'mail' ? 'mailConfig' : 'notifyConfig'; + + const q = useQuery({ queryKey: ['admin-infra', variant], queryFn: apiObj.list, retry: false }); + const [values, setValues] = useState>({}); + + useEffect(() => { + if (q.data) { + const v: Record = {}; + for (const r of q.data) v[r.settingKey] = r.settingValue ?? ''; + setValues(v); + } + }, [q.data]); + + const saveM = useMutation({ + mutationFn: (body: InfraConfigUpdateBody) => apiObj.save(body), + onSuccess: () => { show(t(`${titleKey}.saved`)); qc.invalidateQueries({ queryKey: ['admin-infra', variant] }); }, + onError: (e) => show(errMessage(e)), + }); + + function submit(e: React.FormEvent) { + e.preventDefault(); + const rows = q.data ?? []; + const items = rows.map((r) => ({ settingKey: r.settingKey, settingValue: values[r.settingKey] ?? '' })); + saveM.mutate({ items }); + } + + const rows = q.data ?? []; + + return ( +
+
+
+

{t(`${titleKey}.title`)}

+

{t(`${titleKey}.subtitle`)}

+
+
+ + {q.isLoading && } + {q.isError && !q.isLoading && q.refetch()} />} + + {!q.isLoading && !q.isError && ( +
+
+ {rows.map((r) => ( + setValues((s) => ({ ...s, [r.settingKey]: v }))} /> + ))} +
+
+ +
+
+ )} + {toast} +
+ ); +} + +function ConfigField({ row, value, onChange }: { + row: InfraConfigRow; value: string; onChange: (v: string) => void; +}) { + const isBool = (row.valueType ?? '').toUpperCase() === 'BOOL'; + const isSecret = row.secretYn === 'Y'; + return ( + + ); +} + +export function MailConfigPage() { + return ; +} +export function NotifyConfigPage() { + return ; +} diff --git a/src/frontend/src/screens/admin/LoginHistoryPage.tsx b/src/frontend/src/screens/admin/LoginHistoryPage.tsx new file mode 100644 index 0000000..1c42ca8 --- /dev/null +++ b/src/frontend/src/screens/admin/LoginHistoryPage.tsx @@ -0,0 +1,137 @@ +/* + * W12 시스템관리 — 로그인 이력(접속 세션) 조회 (읽기전용). + * 정본: GET /api/admin/login-history?result&userId&page&size → PageResponse (LoginHistoryController). + * 보안: 이메일/IP 는 백엔드에서 마스킹되어 도착(원문 미저장·미노출, §0-3). + */ +import { useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States'; +import { Button } from '../../components/ui/Button'; +import { IconSearch } from '../../components/ui/icons'; +import { fmtDateTime } from '../work/workShared'; +import { loginHistoryApi } from './systemBasicsApi'; +import './admin-modules.css'; + +const RESULTS = ['', 'SUCCESS', 'FAIL', 'LOCKED']; + +export function LoginHistoryPage() { + const { t } = useTranslation(); + const [result, setResult] = useState(''); + const [userId, setUserId] = useState(''); + const [applied, setApplied] = useState<{ result: string; userId: string }>({ result: '', userId: '' }); + const [page, setPage] = useState(0); + const size = 20; + + const q = useQuery({ + queryKey: ['admin-login-history', applied, page], + queryFn: () => loginHistoryApi.list(applied.result, applied.userId, page, size), + retry: false, + }); + const rows = q.data?.items ?? []; + const total = q.data?.total ?? 0; + const totalPages = Math.max(1, Math.ceil(total / size)); + + return ( +
+
+
+

{t('loginHistory.title')}

+

{t('loginHistory.subtitle')}

+
+
+ +
+
+ + +
+ +
+
+
+ + {q.isLoading && } + {q.isError && !q.isLoading && q.refetch()} />} + + {!q.isLoading && !q.isError && ( +
+ {rows.length === 0 ? ( + + ) : ( + <> +
+ + + + + + + + + + + + + {rows.map((r) => ( + + + + + + + + + ))} + +
{t('loginHistory.colTime')}{t('loginHistory.colResult')}{t('loginHistory.colUser')}{t('loginHistory.colEmail')}{t('loginHistory.colIp')}{t('loginHistory.colReason')}
{fmtDateTime(r.createdAt)}{r.userId ?? '-'}{r.emailMasked ?? '-'}{r.ipMasked ?? '-'}{r.failReason ?? '-'}
+
+ setPage((p) => Math.max(0, p - 1))} + onNext={() => setPage((p) => Math.min(totalPages - 1, p + 1))} /> + + )} +
+ )} +
+ ); +} + +function ResultPill({ value }: { value: string | null }) { + const { t } = useTranslation(); + const v = (value ?? '').toUpperCase(); + const tone = v === 'SUCCESS' ? 'success' : v === 'FAIL' || v === 'LOCKED' ? 'error' : 'neutral'; + const label = v ? t(`loginHistory.result_${v}`) : '-'; + return {label}; +} + +export function Pager({ page, totalPages, total, onPrev, onNext }: { + page: number; totalPages: number; total: number; onPrev: () => void; onNext: () => void; +}) { + const { t } = useTranslation(); + return ( +
+

{t('sysadmin.totalN', { n: total.toLocaleString() })}

+
+ + {page + 1} / {totalPages} + +
+
+ ); +} diff --git a/src/frontend/src/screens/admin/ProgramAdminPage.tsx b/src/frontend/src/screens/admin/ProgramAdminPage.tsx new file mode 100644 index 0000000..b1a3396 --- /dev/null +++ b/src/frontend/src/screens/admin/ProgramAdminPage.tsx @@ -0,0 +1,183 @@ +/* + * W12 시스템관리 — 프로그램(화면) 등록부. + * 정본: GET/POST /api/admin/programs · DELETE /{id} (ProgramController). 라우트/화면 마스터(메뉴와 연결). + */ +import { useState } from 'react'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States'; +import { Button } from '../../components/ui/Button'; +import { IconPlus, IconSearch } from '../../components/ui/icons'; +import { errMessage, useToast } from '../work/workShared'; +import { programApi, PROGRAM_TYPES, type Program, type ProgramSaveBody } from './systemBasicsApi'; +import './admin-modules.css'; + +export function ProgramAdminPage() { + const { t } = useTranslation(); + const qc = useQueryClient(); + const { show, node: toast } = useToast(); + const [keyword, setKeyword] = useState(''); + const [applied, setApplied] = useState(''); + const [editing, setEditing] = useState(undefined); + + const q = useQuery({ + queryKey: ['admin-programs', applied], + queryFn: () => programApi.list(applied || undefined), + retry: false, + }); + const rows = q.data ?? []; + + const saveM = useMutation({ + mutationFn: (body: ProgramSaveBody) => programApi.save(body), + onSuccess: () => { show(t('program.saved')); setEditing(undefined); qc.invalidateQueries({ queryKey: ['admin-programs'] }); }, + onError: (e) => show(errMessage(e)), + }); + const delM = useMutation({ + mutationFn: (id: string) => programApi.remove(id), + onSuccess: () => { show(t('program.deleted')); qc.invalidateQueries({ queryKey: ['admin-programs'] }); }, + onError: (e) => show(errMessage(e)), + }); + + return ( +
+
+
+

{t('program.title')}

+

{t('program.subtitle')}

+
+ +
+ +
+
+ +
+ +
+
+
+ + {q.isLoading && } + {q.isError && !q.isLoading && q.refetch()} />} + + {!q.isLoading && !q.isError && ( +
+ {rows.length === 0 ? ( + + ) : ( +
+ + + + + + + + + + + + {rows.map((r) => ( + + + + + + + + + ))} + +
{t('program.colName')}{t('program.colType')}{t('program.colUrl')}{t('program.colCategory')}{t('program.colUse')} +
{r.programName}{r.programType}{r.programUrl ?? '-'}{r.category ?? '-'}{r.useYn === 'N' ? t('sysadmin.noUse') : t('sysadmin.use')} + + +
+
+ )} +
+ )} + + {editing !== undefined && ( + setEditing(undefined)} onSubmit={(b) => saveM.mutate(b)} /> + )} + {toast} +
+ ); +} + +function ProgramModal({ program, saving, onClose, onSubmit }: { + program: Program | null; saving: boolean; onClose: () => void; onSubmit: (b: ProgramSaveBody) => void; +}) { + const { t } = useTranslation(); + const isNew = program === null; + const [programName, setName] = useState(program?.programName ?? ''); + const [programType, setType] = useState(program?.programType ?? 'SCREEN'); + const [programUrl, setUrl] = useState(program?.programUrl ?? ''); + const [category, setCategory] = useState(program?.category ?? ''); + const [useYn, setUseYn] = useState(program?.useYn ?? 'Y'); + const [error, setError] = useState(null); + + function submit(e: React.FormEvent) { + e.preventDefault(); + if (!programName.trim()) { setError(t('program.errRequired')); return; } + onSubmit({ + id: program?.id ?? null, + programName: programName.trim(), + programType, + programUrl: programUrl.trim() || null, + category: category.trim() || null, + useYn, + }); + } + + return ( +
+
+
+

{isNew ? t('program.add') : t('program.edit')}

+
+ + + + + +
+ {error &&

{error}

} +
+ + +
+
+
+ ); +} diff --git a/src/frontend/src/screens/admin/RoleMenuAdminPage.tsx b/src/frontend/src/screens/admin/RoleMenuAdminPage.tsx new file mode 100644 index 0000000..6aeff47 --- /dev/null +++ b/src/frontend/src/screens/admin/RoleMenuAdminPage.tsx @@ -0,0 +1,148 @@ +/* + * W12 시스템관리 — 역할-메뉴 접근 매핑(역할 × 메뉴 read/write 매트릭스). + * 정본: GET/POST /api/admin/roles/{roleCode}/menus (RoleMenuController). 역할 목록은 기존 roleApi(RoleController). + * 기존 역할/권한(rolePerm=RoleAdminPage)과 직교 — 여긴 메뉴 접근 매핑. + */ +import { useEffect, useState } from 'react'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States'; +import { Button } from '../../components/ui/Button'; +import { errMessage, useToast } from '../work/workShared'; +import { roleApi } from './adminCrudApi'; +import { roleMenuApi, type RoleMenu } from './systemBasicsApi'; +import './admin-modules.css'; + +export function RoleMenuAdminPage() { + const { t } = useTranslation(); + const qc = useQueryClient(); + const { show, node: toast } = useToast(); + const rolesQ = useQuery({ queryKey: ['admin-roles'], queryFn: roleApi.list, retry: false }); + const [selected, setSelected] = useState(null); + const roles = rolesQ.data ?? []; + + useEffect(() => { + if (!selected && roles.length > 0) setSelected(roles[0].roleCode); + }, [roles, selected]); + + const menusQ = useQuery({ + queryKey: ['admin-role-menus', selected], + queryFn: () => roleMenuApi.list(selected!), + enabled: !!selected, + retry: false, + }); + + const [draft, setDraft] = useState>({}); + useEffect(() => { + if (menusQ.data) { + const d: Record = {}; + for (const m of menusQ.data) d[m.menuId] = { readYn: m.readYn, writeYn: m.writeYn, mapped: m.mapped }; + setDraft(d); + } + }, [menusQ.data]); + + const saveM = useMutation({ + mutationFn: () => { + const menus = Object.entries(draft) + .filter(([, v]) => v.mapped) + .map(([menuId, v]) => ({ menuId, readYn: v.readYn, writeYn: v.writeYn })); + return roleMenuApi.save(selected!, { menus }); + }, + onSuccess: () => { show(t('roleMenu.saved')); qc.invalidateQueries({ queryKey: ['admin-role-menus', selected] }); }, + onError: (e) => show(errMessage(e)), + }); + + function toggleMapped(m: RoleMenu, on: boolean) { + setDraft((d) => ({ ...d, [m.menuId]: { ...d[m.menuId], mapped: on, readYn: on ? (d[m.menuId]?.readYn || 'Y') : 'N' } })); + } + function setFlag(m: RoleMenu, key: 'readYn' | 'writeYn', on: boolean) { + setDraft((d) => ({ ...d, [m.menuId]: { ...d[m.menuId], [key]: on ? 'Y' : 'N' } })); + } + + const menus = menusQ.data ?? []; + + return ( +
+
+
+

{t('roleMenu.title')}

+

{t('roleMenu.subtitle')}

+
+ +
+ + {rolesQ.isLoading && } + {rolesQ.isError && !rolesQ.isLoading && rolesQ.refetch()} />} + + {!rolesQ.isLoading && !rolesQ.isError && ( + roles.length === 0 ? ( + + ) : ( +
+
+

{t('roleMenu.role')}

+
    + {roles.map((r) => ( +
  • + +
  • + ))} +
+
+ +
+ {menusQ.isLoading && } + {menusQ.isError && !menusQ.isLoading && menusQ.refetch()} />} + {!menusQ.isLoading && !menusQ.isError && ( + menus.length === 0 ? ( + + ) : ( +
+ + + + + + + + + + + {menus.map((m) => { + const st = draft[m.menuId] ?? { readYn: 'N', writeYn: 'N', mapped: false }; + return ( + + + + + + + ); + })} + +
{t('roleMenu.colMenu')}{t('roleMenu.colAccess')}{t('roleMenu.colRead')}{t('roleMenu.colWrite')}
{m.menuName} + toggleMapped(m, e.target.checked)} /> + + setFlag(m, 'readYn', e.target.checked)} /> + + setFlag(m, 'writeYn', e.target.checked)} /> +
+
+ ) + )} +
+
+ ) + )} + {toast} +
+ ); +} diff --git a/src/frontend/src/screens/admin/SystemHealthPage.tsx b/src/frontend/src/screens/admin/SystemHealthPage.tsx new file mode 100644 index 0000000..12c58f8 --- /dev/null +++ b/src/frontend/src/screens/admin/SystemHealthPage.tsx @@ -0,0 +1,101 @@ +/* + * W12 시스템관리 — 시스템 상태 대시보드. + * 정본: GET /api/admin/system-health → SystemHealth (SystemHealthController). DB/Redis/워커/디스크/메모리/가동시간. + * 보안: 내부IP·스택트레이스 미노출(백엔드 집계값만). + */ +import { useQuery } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { ErrorState, Skeleton } from '../../components/ui/States'; +import { Button } from '../../components/ui/Button'; +import { systemHealthApi, type SystemHealth } from './systemBasicsApi'; +import './admin-modules.css'; + +export function SystemHealthPage() { + const { t } = useTranslation(); + const q = useQuery({ + queryKey: ['admin-system-health'], + queryFn: systemHealthApi.get, + retry: false, + refetchInterval: 15000, + }); + const h = q.data; + + return ( +
+
+
+

{t('sysHealth.title')}

+

{t('sysHealth.subtitle')}

+
+ +
+ + {q.isLoading && } + {q.isError && !q.isLoading && q.refetch()} />} + + {!q.isLoading && !q.isError && h && ( + <> +
+ + + +
+
+ + + + +
+ + )} +
+ ); +} + +function statusTone(v: string): 'success' | 'error' | 'neutral' { + const s = (v ?? '').toUpperCase(); + if (s === 'UP') return 'success'; + if (s === 'DOWN') return 'error'; + return 'neutral'; +} + +function metricPct(n: number): string { + return n < 0 ? 'N/A' : `${n}%`; +} + +function StatusCard({ label, value, sub, tone }: { + label: string; value: string; sub?: string; tone: 'success' | 'error' | 'neutral'; +}) { + return ( +
+ {label} + {value} + {sub && {sub}} +
+ ); +} + +function Metric({ label, value, sub }: { label: string; value: string; sub?: string }) { + return ( +
+ {label} + {value} + {sub && {sub}} +
+ ); +} + +function fmtUptime(sec: number): string { + if (sec < 0) return 'N/A'; + const d = Math.floor(sec / 86400); + const h = Math.floor((sec % 86400) / 3600); + const m = Math.floor((sec % 3600) / 60); + if (d > 0) return `${d}d ${h}h`; + if (h > 0) return `${h}h ${m}m`; + return `${m}m`; +} + +export type { SystemHealth }; diff --git a/src/frontend/src/screens/admin/admin-modules.css b/src/frontend/src/screens/admin/admin-modules.css index f4a287c..77e0348 100644 --- a/src/frontend/src/screens/admin/admin-modules.css +++ b/src/frontend/src/screens/admin/admin-modules.css @@ -601,3 +601,59 @@ .kx-adm-modal__grid { grid-template-columns: 1fr; } .kx-adm-toolbar { flex-direction: column; align-items: stretch; } } + +/* ═══════════ W12 시스템관리 기본기(조직·프로그램·역할메뉴·인증정책·이력·상태·설정) ═══════════ */ +/* 부서 트리 */ +.kx-adm-tree { list-style: none; margin: 0; padding: var(--space-2) 0; display: grid; } +.kx-adm-tree__row { + display: flex; align-items: center; justify-content: space-between; + padding: 10px 12px; border-bottom: 1px solid var(--color-neutral-100); +} +.kx-adm-tree__row:last-child { border-bottom: none; } +.kx-adm-tree__name { font-size: var(--fs-body); color: var(--color-neutral-900); } +.kx-adm-tree__actions { display: inline-flex; gap: var(--space-2); } + +/* 시스템 상태 카드 */ +.kx-adm-health-grid { + display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-3); margin-bottom: var(--space-3); +} +.kx-adm-health-card { + display: flex; flex-direction: column; gap: 4px; padding: var(--space-4); + border-left: 4px solid var(--color-neutral-200); +} +.kx-adm-health-card--success { border-left-color: var(--color-success); } +.kx-adm-health-card--error { border-left-color: var(--color-error); } +.kx-adm-health-card--neutral { border-left-color: var(--color-warning); } +.kx-adm-health-card__label { font-size: var(--fs-caption); color: var(--color-neutral-500); } +.kx-adm-health-card__value { font-size: var(--fs-h2); font-weight: 700; color: var(--color-neutral-900); } +.kx-adm-health-card__sub { font-size: var(--fs-caption); color: var(--color-neutral-500); } +.kx-adm-metrics { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4); } +.kx-adm-metric { display: flex; flex-direction: column; gap: 4px; } +.kx-adm-metric__label { font-size: var(--fs-caption); color: var(--color-neutral-500); } +.kx-adm-metric__value { font-size: var(--fs-h3); font-weight: 700; color: var(--color-neutral-900); } +.kx-adm-metric__sub { font-size: var(--fs-caption); color: var(--color-neutral-500); } + +/* 폼(인증정책·설정) */ +.kx-adm-form { display: grid; gap: var(--space-3); } +.kx-adm-form__section { + font-size: var(--fs-h3); font-weight: 700; color: var(--color-neutral-900); + margin: var(--space-2) 0 0; padding-top: var(--space-2); border-top: 1px solid var(--color-neutral-100); +} +.kx-adm-form__section:first-child { border-top: none; padding-top: 0; } + +/* 메일/알림 설정 */ +.kx-adm-config-list { display: grid; gap: var(--space-3); } +.kx-adm-config-field { + display: grid; grid-template-columns: 1fr 260px; gap: var(--space-3); align-items: center; + padding-bottom: var(--space-2); border-bottom: 1px solid var(--color-neutral-100); +} +.kx-adm-config-field__key { display: flex; flex-direction: column; gap: 2px; } +.kx-adm-config-field__desc { font-size: var(--fs-caption); color: var(--color-neutral-500); } + +.kx-adm-center { text-align: center; } + +@media (max-width: 1024px) { + .kx-adm-health-grid { grid-template-columns: 1fr; } + .kx-adm-metrics { grid-template-columns: 1fr 1fr; } + .kx-adm-config-field { grid-template-columns: 1fr; } +} diff --git a/src/frontend/src/screens/admin/systemBasicsApi.ts b/src/frontend/src/screens/admin/systemBasicsApi.ts new file mode 100644 index 0000000..a4e5c2c --- /dev/null +++ b/src/frontend/src/screens/admin/systemBasicsApi.ts @@ -0,0 +1,233 @@ +/* + * W12 시스템관리 기본기(1차) 실배선 API 계약. 공용 클라이언트(../../api/client)만 사용 + * — client.ts·endpoints.ts·types.ts 무수정. + * 정본: 백엔드 컨트롤러 시그니처(com.zioinfo.kintex.system.*, V37 스키마). + * 조직 /api/admin/depts (트리) · /api/admin/companies (PageResponse) + * 프로그램 /api/admin/programs + * 역할-메뉴 /api/admin/roles/{roleCode}/menus + * 인증정책 /api/admin/auth-policy + * 로그인이력 /api/admin/login-history (PageResponse, 읽기전용) + * 오류로그 /api/admin/error-log (PageResponse, 읽기전용) + * 시스템상태 /api/admin/system-health + * 메일/알림 /api/admin/mail-config · /api/admin/notify-config + * ★ 보안: 연락처(회사)·이메일/IP(로그인이력)는 백엔드에서 마스킹되어 도착한다. + * 시크릿 설정(mail.password 등)은 secretYn='Y'로 마스킹(********) 도착 — 미변경 시 저장 전송 제외. + */ +import { api } from '../../api/client'; +import type { PageResponse } from '../../api/types'; + +// ══════════ 1. 조직 — 부서 트리 ══════════ +export interface DeptNode { + id: string; + deptName: string; + parentId: string | null; + sortOrder: number; + useYn: string | null; + children?: DeptNode[]; +} +export interface DeptSaveBody { + id?: string | null; + deptName: string; + parentId?: string | null; + sortOrder?: number | null; + useYn?: string | null; +} +export const deptApi = { + tree: () => api.get('/api/admin/depts'), + save: (body: DeptSaveBody) => api.post('/api/admin/depts', body), + remove: (id: string) => api.del(`/api/admin/depts/${encodeURIComponent(id)}`), +}; + +// ══════════ 1. 조직 — 회사(거래처) ══════════ +export interface Company { + id: string; + companyName: string; + bizNo: string | null; + ceoName: string | null; + bizType: string | null; + contactName: string | null; + contactTel: string | null; // 마스킹됨 + address: string | null; + partnerType: string | null; + useYn: string | null; +} +export interface CompanySaveBody { + id?: string | null; + companyName: string; + bizNo?: string | null; + ceoName?: string | null; + bizType?: string | null; + contactName?: string | null; + contactTel?: string | null; + address?: string | null; + partnerType?: string | null; + useYn?: string | null; +} +export interface CompanySearchParams { + keyword?: string; + partnerType?: string; + page?: number; + size?: number; +} +export const companyApi = { + list: (p: CompanySearchParams = {}) => { + const qs = new URLSearchParams(); + if (p.keyword) qs.set('keyword', p.keyword); + if (p.partnerType) qs.set('partnerType', p.partnerType); + qs.set('page', String(p.page ?? 0)); + qs.set('size', String(p.size ?? 20)); + return api.get>(`/api/admin/companies?${qs.toString()}`); + }, + save: (body: CompanySaveBody) => api.post('/api/admin/companies', body), + remove: (id: string) => api.del(`/api/admin/companies/${encodeURIComponent(id)}`), +}; +export const PARTNER_TYPES = ['CONTRACTOR', 'SUPPLIER', 'AGENCY', 'ETC'] as const; + +// ══════════ 2. 프로그램(화면) ══════════ +export interface Program { + id: string; + programName: string; + programType: string | null; + programUrl: string | null; + category: string | null; + useYn: string | null; +} +export interface ProgramSaveBody { + id?: string | null; + programName: string; + programType?: string | null; + programUrl?: string | null; + category?: string | null; + useYn?: string | null; +} +export const programApi = { + list: (keyword?: string, category?: string) => { + const qs = new URLSearchParams(); + if (keyword) qs.set('keyword', keyword); + if (category) qs.set('category', category); + const s = qs.toString(); + return api.get(`/api/admin/programs${s ? `?${s}` : ''}`); + }, + save: (body: ProgramSaveBody) => api.post('/api/admin/programs', body), + remove: (id: string) => api.del(`/api/admin/programs/${encodeURIComponent(id)}`), +}; +export const PROGRAM_TYPES = ['SCREEN', 'POPUP', 'LINK'] as const; + +// ══════════ 3. 역할-메뉴 매핑 ══════════ +export interface RoleMenu { + menuId: string; + menuName: string; + parentId: string | null; + sortOrder: number; + mapped: boolean; + readYn: string; + writeYn: string; +} +export interface RoleMenuSaveBody { + menus: { menuId: string; readYn: string; writeYn: string }[]; +} +export const roleMenuApi = { + list: (roleCode: string) => + api.get(`/api/admin/roles/${encodeURIComponent(roleCode)}/menus`), + save: (roleCode: string, body: RoleMenuSaveBody) => + api.post(`/api/admin/roles/${encodeURIComponent(roleCode)}/menus`, body), +}; + +// ══════════ 4. 인증 정책 ══════════ +export interface AuthPolicy { + pwMinLength: number; + pwRequireUpper: string; + pwRequireNumber: string; + pwRequireSpecial: string; + pwExpireDays: number; + loginMaxFail: number; + lockMinutes: number; + sessionTimeoutMin: number; + updatedAt: string | null; + updatedBy: string | null; +} +export type AuthPolicySaveBody = Omit; +export const authPolicyApi = { + get: () => api.get('/api/admin/auth-policy'), + save: (body: AuthPolicySaveBody) => api.put('/api/admin/auth-policy', body), +}; + +// ══════════ 5. 로그인 이력(읽기전용) ══════════ +export interface LoginHistoryRow { + id: number; + userId: string | null; + emailMasked: string | null; + result: string | null; + failReason: string | null; + ipMasked: string | null; + userAgent: string | null; + createdAt: string | null; +} +export const loginHistoryApi = { + list: (result: string, userId: string, page: number, size: number) => { + const qs = new URLSearchParams(); + if (result) qs.set('result', result); + if (userId) qs.set('userId', userId); + qs.set('page', String(page)); + qs.set('size', String(size)); + return api.get>(`/api/admin/login-history?${qs.toString()}`); + }, +}; + +// ══════════ 6. 오류 로그(읽기전용) ══════════ +export interface ErrorLogRow { + id: number; + errorCode: string | null; + summary: string | null; + path: string | null; + method: string | null; + actorId: string | null; + createdAt: string | null; +} +export const errorLogApi = { + list: (errorCode: string, page: number, size: number) => { + const qs = new URLSearchParams(); + if (errorCode) qs.set('errorCode', errorCode); + qs.set('page', String(page)); + qs.set('size', String(size)); + return api.get>(`/api/admin/error-log?${qs.toString()}`); + }, +}; + +// ══════════ 7. 시스템 상태 ══════════ +export interface SystemHealth { + db: string; + redis: string; + worker: string; + queueDepth: number; + diskFreePct: number; + diskFreeMb: number; + memUsedPct: number; + uptimeSec: number; + version: string; + time: string; +} +export const systemHealthApi = { + get: () => api.get('/api/admin/system-health'), +}; + +// ══════════ 8. 메일/알림 설정 ══════════ +export interface InfraConfigRow { + settingKey: string; + settingValue: string | null; + valueType: string | null; + description: string | null; + secretYn: string | null; +} +export interface InfraConfigUpdateBody { + items: { settingKey: string; settingValue: string | null }[]; +} +export const CONFIG_MASK = '********'; +export const mailConfigApi = { + list: () => api.get('/api/admin/mail-config'), + save: (body: InfraConfigUpdateBody) => api.put('/api/admin/mail-config', body), +}; +export const notifyConfigApi = { + list: () => api.get('/api/admin/notify-config'), + save: (body: InfraConfigUpdateBody) => api.put('/api/admin/notify-config', body), +}; diff --git a/src/frontend/src/screens/appqr/AppQrCode.tsx b/src/frontend/src/screens/appqr/AppQrCode.tsx new file mode 100644 index 0000000..e21e956 --- /dev/null +++ b/src/frontend/src/screens/appqr/AppQrCode.tsx @@ -0,0 +1,392 @@ +// 자체 QR 코드 생성기(외부 API/라이브러리 0) — 앱 다운로드 URL을 인코딩해 SVG로 렌더. +// 정본: WISE(UIWS) frontend/src/pages/AppQrCode.tsx 를 구조 그대로 이식. +// +// 외부 API 금지·신규 npm 의존성 0 제약을 준수하기 위해 QR(Model 2, byte 모드, EC level M)을 +// 직접 구현한다. 다운로드 URL이 빌드마다 매니페스트로 바뀌어도 항상 라이브 URL을 인코딩한다. +// (api.qrserver.com 등 외부 QR 생성 서비스 미사용.) +// +// 정확성: 기능 패턴(파인더/정렬/타이밍/포맷/다크모듈)을 reserved 매트릭스로 분리 추적하여 +// 데이터 비트 배치·마스킹이 기능 셀을 건드리지 않도록 한다. mask 0 고정(format 비트는 사전계산). +import { useMemo } from 'react'; + +// ── GF(256) 로그/역로그 테이블(Reed-Solomon EC용) ── +const EXP = new Uint8Array(512); +const LOG = new Uint8Array(256); +(() => { + let x = 1; + for (let i = 0; i < 255; i++) { + EXP[i] = x; + LOG[x] = i; + x <<= 1; + if (x & 0x100) x ^= 0x11d; + } + for (let i = 255; i < 512; i++) EXP[i] = EXP[i - 255]; +})(); + +function gfMul(a: number, b: number): number { + if (a === 0 || b === 0) return 0; + return EXP[LOG[a] + LOG[b]]; +} + +function rsGenPoly(degree: number): number[] { + // 생성 다항식 g(x) = ∏(x − α^i), poly[0]이 최고차 계수(=1)가 되도록 누적한다. + // rsEncode는 gen[0]을 선두(최고차) 계수로 소비하므로 계수 순서가 반대가 되면 EC가 전부 틀어진다. + // (x + α^i) 곱셈: x·poly는 같은 인덱스 유지(차수 +1), α^i·poly는 상수항 쪽(j+1)으로. + let poly = [1]; + for (let i = 0; i < degree; i++) { + const next = new Array(poly.length + 1).fill(0); + for (let j = 0; j < poly.length; j++) { + next[j] ^= poly[j]; + next[j + 1] ^= gfMul(poly[j], EXP[i]); + } + poly = next; + } + return poly; +} + +function rsEncode(data: number[], ecLen: number): number[] { + const gen = rsGenPoly(ecLen); + const res = new Array(data.length + ecLen).fill(0); + for (let i = 0; i < data.length; i++) res[i] = data[i]; + for (let i = 0; i < data.length; i++) { + const coef = res[i]; + if (coef !== 0) { + for (let j = 0; j < gen.length; j++) res[i + j] ^= gfMul(gen[j], coef); + } + } + return res.slice(data.length); +} + +// ── 버전별 파라미터(EC level M, byte 모드) — 버전 1~10 (URL 길이 충분히 커버) ── +interface VerSpec { + size: number; // 모듈 한 변 + ec: number; // 블록당 EC 코드워드 + g1: number; // 그룹1 블록 수 + g1d: number; // 그룹1 블록당 데이터 코드워드 + g2: number; // 그룹2 블록 수 + g2d: number; // 그룹2 블록당 데이터 코드워드 + cap: number; // 총 데이터 코드워드(= g1*g1d + g2*g2d) +} +const SPECS: Record = { + 1: { size: 21, ec: 10, g1: 1, g1d: 16, g2: 0, g2d: 0, cap: 16 }, + 2: { size: 25, ec: 16, g1: 1, g1d: 28, g2: 0, g2d: 0, cap: 28 }, + 3: { size: 29, ec: 26, g1: 1, g1d: 44, g2: 0, g2d: 0, cap: 44 }, + 4: { size: 33, ec: 18, g1: 2, g1d: 32, g2: 0, g2d: 0, cap: 64 }, + 5: { size: 37, ec: 24, g1: 2, g1d: 43, g2: 0, g2d: 0, cap: 86 }, + 6: { size: 41, ec: 16, g1: 4, g1d: 27, g2: 0, g2d: 0, cap: 108 }, + 7: { size: 45, ec: 18, g1: 4, g1d: 31, g2: 0, g2d: 0, cap: 124 }, + 8: { size: 49, ec: 22, g1: 2, g1d: 38, g2: 2, g2d: 39, cap: 154 }, + 9: { size: 53, ec: 22, g1: 3, g1d: 36, g2: 2, g2d: 37, cap: 182 }, + 10: { size: 57, ec: 26, g1: 4, g1d: 43, g2: 1, g2d: 44, cap: 216 }, +}; + +// 정렬 패턴 중심 좌표 +const ALIGN: Record = { + 1: [], + 2: [6, 18], + 3: [6, 22], + 4: [6, 26], + 5: [6, 30], + 6: [6, 34], + 7: [6, 22, 38], + 8: [6, 24, 42], + 9: [6, 26, 46], + 10: [6, 28, 50], +}; + +// 포맷 정보(EC level M, mask 0~7) 15bit 시퀀스(사전계산, BCH+마스크 0x5412 적용분) +const FORMAT_M: number[] = [ + 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, +]; + +// 버전 정보(18bit, BCH(18,6) 사전계산) — 버전 7~40만 사용. 6 이하는 버전 정보 모듈 없음. +// ★ 이 모듈이 누락되면 버전 7+ QR을 표준 스캐너가 디코드하지 못한다(원인2). +// 값은 ISO/IEC 18004 부록 D 표와 동일(버전 7~10). +const VERSION_INFO: Record = { + 7: 0x07c94, + 8: 0x085bc, + 9: 0x09a99, + 10: 0x0a4d3, +}; + +function bytesOf(str: string): number[] { + return Array.from(new TextEncoder().encode(str)); +} + +function chooseVersion(len: number): number { + // +2 코드워드 여유(모드 지시자 4bit + 카운트 8/16bit) + for (let v = 1; v <= 10; v++) if (SPECS[v].cap >= len + 2) return v; + return 10; +} + +// byte 모드 데이터 코드워드 생성 +function buildData(bytes: number[], spec: VerSpec, version: number): number[] { + const bits: number[] = []; + const push = (val: number, n: number) => { + for (let i = n - 1; i >= 0; i--) bits.push((val >> i) & 1); + }; + push(0b0100, 4); // byte 모드 + push(bytes.length, version >= 10 ? 16 : 8); // 카운트(버전 1~9는 8bit) + for (const b of bytes) push(b, 8); + const capBits = spec.cap * 8; + for (let i = 0; i < 4 && bits.length < capBits; i++) bits.push(0); // 종료 + while (bits.length % 8 !== 0) bits.push(0); + const pad = [0xec, 0x11]; + let pi = 0; + while (bits.length < capBits) { + push(pad[pi % 2], 8); + pi++; + } + const cw: number[] = []; + for (let i = 0; i < bits.length; i += 8) { + let v = 0; + for (let j = 0; j < 8; j++) v = (v << 1) | bits[i + j]; + cw.push(v); + } + return cw; +} + +// 데이터 + EC 블록 인터리브 +function interleave(dataCw: number[], spec: VerSpec): number[] { + const blocks: { data: number[]; ec: number[] }[] = []; + let idx = 0; + for (let i = 0; i < spec.g1; i++) { + const d = dataCw.slice(idx, idx + spec.g1d); + idx += spec.g1d; + blocks.push({ data: d, ec: rsEncode(d, spec.ec) }); + } + for (let i = 0; i < spec.g2; i++) { + const d = dataCw.slice(idx, idx + spec.g2d); + idx += spec.g2d; + blocks.push({ data: d, ec: rsEncode(d, spec.ec) }); + } + const out: number[] = []; + const maxData = Math.max(spec.g1d, spec.g2d); + for (let i = 0; i < maxData; i++) { + for (const b of blocks) if (i < b.data.length) out.push(b.data[i]); + } + for (let i = 0; i < spec.ec; i++) for (const b of blocks) out.push(b.ec[i]); + return out; +} + +function makeMatrix(size: number): { m: number[][]; reserved: boolean[][] } { + const m = Array.from({ length: size }, () => new Array(size).fill(0)); + const reserved = Array.from({ length: size }, () => new Array(size).fill(false)); + return { m, reserved }; +} + +function setF(m: number[][], reserved: boolean[][], r: number, c: number, v: number) { + if (r < 0 || c < 0 || r >= m.length || c >= m.length) return; + m[r][c] = v; + reserved[r][c] = true; +} + +function placeFinder(m: number[][], reserved: boolean[][], r: number, c: number) { + for (let i = -1; i <= 7; i++) { + for (let j = -1; j <= 7; j++) { + const rr = r + i; + const cc = c + j; + if (rr < 0 || cc < 0 || rr >= m.length || cc >= m.length) continue; + if (i === -1 || i === 7 || j === -1 || j === 7) { + setF(m, reserved, rr, cc, 0); // 분리자(흰) + } else { + const onBorder = i === 0 || i === 6 || j === 0 || j === 6; + const inside = i >= 2 && i <= 4 && j >= 2 && j <= 4; + setF(m, reserved, rr, cc, onBorder || inside ? 1 : 0); + } + } + } +} + +function placeAlign(m: number[][], reserved: boolean[][], version: number) { + const centers = ALIGN[version]; + for (const r of centers) { + for (const c of centers) { + if (reserved[r][c]) continue; // 파인더와 겹침 + for (let i = -2; i <= 2; i++) { + for (let j = -2; j <= 2; j++) { + const ring = Math.max(Math.abs(i), Math.abs(j)); + setF(m, reserved, r + i, c + j, ring === 1 ? 0 : 1); + } + } + } + } +} + +function placeTiming(m: number[][], reserved: boolean[][]) { + const size = m.length; + for (let i = 8; i < size - 8; i++) { + const v = i % 2 === 0 ? 1 : 0; + if (!reserved[6][i]) setF(m, reserved, 6, i, v); + if (!reserved[i][6]) setF(m, reserved, i, 6, v); + } +} + +// 포맷 정보 영역 예약 + 다크 모듈(값은 placeFormat에서 채움, 여기선 reserved만) +function reserveFormat(m: number[][], reserved: boolean[][]) { + const size = m.length; + for (let i = 0; i <= 8; i++) { + if (!reserved[8][i]) reserved[8][i] = true; + if (!reserved[i][8]) reserved[i][8] = true; + } + for (let i = 0; i < 8; i++) { + reserved[8][size - 1 - i] = true; + reserved[size - 1 - i][8] = true; + } + setF(m, reserved, size - 8, 8, 1); // 다크 모듈 +} + +function placeData(m: number[][], reserved: boolean[][], cw: number[]) { + const size = m.length; + let bitIdx = 0; + const totalBits = cw.length * 8; + const bitAt = (i: number) => (i < totalBits ? (cw[i >> 3] >> (7 - (i & 7))) & 1 : 0); + let up = true; + for (let col = size - 1; col > 0; col -= 2) { + if (col === 6) col--; // timing 열 skip + for (let n = 0; n < size; n++) { + const row = up ? size - 1 - n : n; + for (let c = 0; c < 2; c++) { + const cc = col - c; + if (!reserved[row][cc]) { + m[row][cc] = bitAt(bitIdx); + bitIdx++; + } + } + } + up = !up; + } +} + +// 데이터 영역에만 마스크 적용(기능/예약 셀 제외). mask 0: (r+c)%2==0 +function applyMask0(m: number[][], reserved: boolean[][]) { + const size = m.length; + for (let r = 0; r < size; r++) { + for (let c = 0; c < size; c++) { + if (reserved[r][c]) continue; + if ((r + c) % 2 === 0) m[r][c] ^= 1; + } + } +} + +function placeFormat(m: number[][], mask: number) { + // 포맷 정보(15bit) 배치 — ISO/IEC 18004 표준 위치·비트순서. + // 주 사본(좌상단): 가로 (8,0..5)=bit14..9, (8,7)=bit8, (8,8)=bit7 / + // 세로 (7,8)=bit6, (5,8)=bit5, (4,8)..(0,8)=bit4..0 (타이밍행 6 건너뜀) + // 부 사본: 좌하단 세로 (size-1-i,8)=bit(14-i) i=0..6(비트 14~8) / + // 우상단 가로 (8,size-8+i)=bit(7-i) i=0..7(비트 7~0) + // 다크 모듈 m[size-8][8](항상 1)은 어느 사본도 침범하지 않는다. + const size = m.length; + const fmt = FORMAT_M[mask]; + const bit = (i: number) => (fmt >> i) & 1; + // 주 사본 — 가로(행 8) + for (let i = 0; i <= 5; i++) m[8][i] = bit(14 - i); // (8,0..5) = bit14..9 + m[8][7] = bit(8); + m[8][8] = bit(7); + // 주 사본 — 세로(열 8) + m[7][8] = bit(6); + for (let i = 0; i <= 4; i++) m[4 - i][8] = bit(4 - i); // (4,8)..(0,8) = bit4..0 + // 부 사본 — 좌하단 세로(비트 14~8) + for (let i = 0; i <= 6; i++) m[size - 1 - i][8] = bit(14 - i); + // 부 사본 — 우상단 가로(비트 7~0) + for (let i = 0; i <= 7; i++) m[8][size - 8 + i] = bit(7 - i); +} + +// 버전 정보(18bit) 예약 + 배치 — 버전 7~40만. 좌하단 6×3 블록 + 우상단 3×6 블록. +// bit i(i=0..17): 좌하단 (size-11 + i%3, ⌊i/3⌋), 우상단 (⌊i/3⌋, size-11 + i%3). +function reserveVersion(m: number[][], reserved: boolean[][], version: number) { + if (version < 7) return; + const size = m.length; + for (let i = 0; i < 18; i++) { + const r = i % 3; + const c = Math.floor(i / 3); + reserved[size - 11 + r][c] = true; // 좌하단 + reserved[c][size - 11 + r] = true; // 우상단 + } +} +function placeVersion(m: number[][], version: number) { + if (version < 7) return; + const size = m.length; + const v = VERSION_INFO[version]; + if (v === undefined) return; + for (let i = 0; i < 18; i++) { + const bit = (v >> i) & 1; + const r = i % 3; + const c = Math.floor(i / 3); + m[size - 11 + r][c] = bit; // 좌하단 + m[c][size - 11 + r] = bit; // 우상단 + } +} + +function generateMatrix(text: string): number[][] { + const bytes = bytesOf(text); + const version = chooseVersion(bytes.length); + const spec = SPECS[version]; + const dataCw = buildData(bytes, spec, version); + const finalCw = interleave(dataCw, spec); + + const { m, reserved } = makeMatrix(spec.size); + placeFinder(m, reserved, 0, 0); + placeFinder(m, reserved, 0, spec.size - 7); + placeFinder(m, reserved, spec.size - 7, 0); + placeAlign(m, reserved, version); + placeTiming(m, reserved); + reserveFormat(m, reserved); + reserveVersion(m, reserved, version); // 버전 7+ 정보 영역 예약(데이터 침범 방지) + placeData(m, reserved, finalCw); + applyMask0(m, reserved); + placeFormat(m, 0); + placeVersion(m, version); // 버전 7+ 정보 모듈 기입 + return m; +} + +interface Props { + value: string; + size?: number; + title?: string; +} + +/** 다운로드 URL을 인코딩한 QR 코드를 SVG로 렌더(외부 의존성 0). */ +export default function AppQrCode({ value, size = 200, title = 'QR 코드' }: Props) { + const matrix = useMemo(() => { + try { + return generateMatrix(value); + } catch { + return null; + } + }, [value]); + + if (!matrix) { + return ( +
+ QR을 표시할 수 없습니다 +
+ ); + } + + const n = matrix.length; + const quiet = 4; // 정숙 영역 4 모듈 + const total = n + quiet * 2; + const cells: string[] = []; + for (let r = 0; r < n; r++) { + for (let c = 0; c < n; c++) { + if (matrix[r][c]) cells.push(`M${c + quiet} ${r + quiet}h1v1h-1z`); + } + } + + return ( + + + + + ); +} diff --git a/src/frontend/src/screens/appqr/AppQrCodePage.tsx b/src/frontend/src/screens/appqr/AppQrCodePage.tsx new file mode 100644 index 0000000..ba7c03d --- /dev/null +++ b/src/frontend/src/screens/appqr/AppQrCodePage.tsx @@ -0,0 +1,204 @@ +/* + * SCR-APPQR 모바일 앱 설치 QR 페이지. 정본: WISE(UIWS) pages/MobileApp.tsx 구조 이식. + * 라우트 계약: /app-qr (App.tsx 배선은 통합자 관할 — _workspace/impl_appqr.md 참조). + * + * APK 자체 호스팅: 다운로드 URL = /downloads/kintex.apk (nginx 서빙, 서버 배치는 통합자). + * 버전 매니페스트 = /downloads/kintex-app.json ({ version, builtAt, size }). + * - 200: QR + 버전 정보 + 다운로드/링크복사 + 설치 안내 스텝 표시. + * - 404/실패: "앱 빌드 준비 중" 빈 상태 — APK가 아직 없음(EAS 빌드 G3 게이트)을 정직 표기. + * QR은 다운로드 URL을 자체 인코딩(AppQrCode, 외부 API/라이브러리 0). + */ +import { useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import AppQrCode from './AppQrCode'; +import { Button } from '../../components/ui/Button'; +import { EmptyState, Skeleton } from '../../components/ui/States'; +import { + IconDownload, + IconCheck, + IconOperations, + IconGrid, + IconWifiOff, +} from '../../components/ui/icons'; +import './appqr.css'; + +/** 매니페스트 계약(/downloads/kintex-app.json). 모든 필드 선택 — 부재해도 graceful. */ +interface AppManifest { + version?: string; + builtAt?: string; + /** 바이트 수(number) 또는 "24MB" 같은 표기(string) 모두 허용. */ + size?: number | string; +} + +const MANIFEST_URL = '/downloads/kintex-app.json'; +const APK_URL = '/downloads/kintex.apk'; + +/** 다운로드 절대 URL — 휴대폰 스캐너가 바로 접근하도록 origin 결합. */ +function absoluteApkUrl(): string { + if (typeof window !== 'undefined' && window.location?.origin) { + return `${window.location.origin}${APK_URL}`; + } + return APK_URL; +} + +function formatSize(size?: number | string): string | null { + if (size == null) return null; + if (typeof size === 'string') return size; + if (size <= 0) return null; + const mb = size / (1024 * 1024); + return `${mb >= 10 ? Math.round(mb) : mb.toFixed(1)}MB`; +} + +type Phase = 'loading' | 'ready' | 'unavailable'; + +export function AppQrCodePage() { + const { t } = useTranslation(); + const [phase, setPhase] = useState('loading'); + const [manifest, setManifest] = useState(null); + const [copied, setCopied] = useState(false); + + const load = useCallback(async () => { + setPhase('loading'); + try { + const res = await fetch(MANIFEST_URL, { cache: 'no-store' }); + if (!res.ok) { + // 404 = APK 미빌드(G3 게이트). "빌드 준비 중" 상태로 정직 표기. + setManifest(null); + setPhase('unavailable'); + return; + } + const data = (await res.json()) as AppManifest; + setManifest(data); + setPhase('ready'); + } catch { + // 네트워크/파싱 실패도 동일하게 미가용 처리(외부 QR 서비스 호출 없음). + setManifest(null); + setPhase('unavailable'); + } + }, []); + + useEffect(() => { + void load(); + }, [load]); + + const copyLink = async () => { + try { + await navigator.clipboard.writeText(absoluteApkUrl()); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch { + /* clipboard 권한 없을 때 무시 */ + } + }; + + const version = manifest?.version ?? null; + const builtAt = manifest?.builtAt ?? null; + const sizeLabel = formatSize(manifest?.size); + const metaParts = ['Android', 'APK']; + if (sizeLabel) metaParts.push(t('appqr.about', { size: sizeLabel })); + + const steps = [ + t('appqr.steps.s1'), + t('appqr.steps.s2'), + t('appqr.steps.s3'), + t('appqr.steps.s4'), + ]; + + return ( +
+
+
+

{t('appqr.title')}

+

{t('appqr.subtitle')}

+
+
+ +

{t('appqr.intro')}

+ + {phase === 'loading' ? ( +
+ +
+ + + +
+
+ ) : phase === 'unavailable' ? ( +
+ } + title={t('appqr.notReady.title')} + description={t('appqr.notReady.desc')} + action={ + + } + /> +
+ ) : ( +
+
+ {/* 다운로드 URL을 자체 인코딩한 QR(외부 API 0). */} + +
+ +
+
+ + {t('appqr.appName')} + {version ? v{version} : null} +
+ +

{metaParts.join(' · ')}

+ {builtAt ? ( +

{t('appqr.builtAt', { date: builtAt })}

+ ) : null} + +
+ + + {t('appqr.download')} + + + +
+ +

{t('appqr.iosNote')}

+
+
+ )} + +
+

{t('appqr.steps.heading')}

+
    + {steps.map((s, i) => ( +
  1. + + {s} +
  2. + ))} +
+
+
+ ); +} + +export default AppQrCodePage; diff --git a/src/frontend/src/screens/appqr/appqr.css b/src/frontend/src/screens/appqr/appqr.css new file mode 100644 index 0000000..c45fa92 --- /dev/null +++ b/src/frontend/src/screens/appqr/appqr.css @@ -0,0 +1,154 @@ +/* + * SCR-APPQR 모바일 앱 설치 QR 페이지 전용 스타일. + * design.md §1 토큰만 참조. shared.css 프리미티브(kx-page·kx-card) 위에 얹는다. + * 정본: WISE(UIWS) pages/MobileApp.css 구조 이식(토큰만 kintex로 치환). + */ +@import '../shared.css'; + +.kx-appqr { + max-width: 900px; +} + +/* ── 페이지 헤더 ── */ +.kx-appqr__head { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: var(--space-4); + flex-wrap: wrap; +} +.kx-appqr__title { + font-size: var(--fs-h2); + color: var(--color-neutral-900); +} +.kx-appqr__subtitle { + margin-top: 2px; + font-size: var(--fs-body); + color: var(--color-neutral-500); +} +.kx-appqr__intro { + font-size: var(--fs-body); + color: var(--color-neutral-500); + line-height: 1.6; + margin: 0; + max-width: 720px; +} + +/* ── QR + 정보 카드 ── */ +.kx-appqr__card { + display: grid; + grid-template-columns: 232px 1fr; + gap: var(--space-5); + align-items: start; +} +@media (max-width: 640px) { + .kx-appqr__card { + grid-template-columns: 1fr; + } +} + +.kx-appqr__qr { + background: var(--color-white); + border: var(--border-card); + border-radius: var(--radius-lg); + padding: var(--space-3); + display: flex; + align-items: center; + justify-content: center; +} +.kx-appqr__qr svg { + width: 100%; + max-width: 200px; + height: auto; + display: block; +} + +.kx-appqr__body { + display: flex; + flex-direction: column; + gap: var(--space-2); +} +.kx-appqr__name-row { + display: flex; + align-items: center; + gap: var(--space-2); + color: var(--color-neutral-700); +} +.kx-appqr__name { + font-size: var(--fs-h3); + font-weight: 700; + color: var(--color-neutral-900); +} +.kx-appqr__ver { + font-size: var(--fs-caption); + font-weight: 700; + color: var(--color-white); + background: var(--color-primary-600); + border-radius: var(--radius-pill); + padding: 2px 10px; +} +.kx-appqr__meta { + font-size: var(--fs-body); + color: var(--color-neutral-500); + margin: 0; +} +.kx-appqr__ios { + font-size: var(--fs-caption); + color: var(--color-neutral-500); + margin: var(--space-2) 0 0; +} + +.kx-appqr__actions { + display: flex; + flex-wrap: wrap; + gap: var(--space-2); + margin-top: var(--space-2); +} +/* 다운로드는 이지만 kx-btn 룩을 그대로 사용(버튼 컴포넌트와 정렬) */ +.kx-appqr__actions .kx-btn { + text-decoration: none; +} + +/* ── 설치 안내 스텝 ── */ +.kx-appqr__steps-section { + margin-top: var(--space-2); +} +.kx-appqr__steps-heading { + font-size: var(--fs-h3); + color: var(--color-neutral-900); + margin: 0 0 var(--space-3); +} +.kx-appqr__steps { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: var(--space-3); +} +.kx-appqr__step { + display: flex; + align-items: flex-start; + gap: var(--space-3); + padding: var(--space-4); + border: var(--border-card); + border-radius: var(--radius-lg); + background: var(--color-white); +} +.kx-appqr__step-num { + flex: none; + width: 26px; + height: 26px; + display: grid; + place-items: center; + border-radius: var(--radius-pill); + background: var(--color-primary-050); + color: var(--color-primary-700); + font-size: var(--fs-caption); + font-weight: 700; +} +.kx-appqr__step-text { + font-size: var(--fs-body); + color: var(--color-neutral-700); + line-height: 1.55; +} diff --git a/src/frontend/src/screens/home/HomeCharts.tsx b/src/frontend/src/screens/home/HomeCharts.tsx new file mode 100644 index 0000000..845158b --- /dev/null +++ b/src/frontend/src/screens/home/HomeCharts.tsx @@ -0,0 +1,197 @@ +import { useMemo } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { useTranslation } from 'react-i18next'; +import { + Bar, + BarChart, + CartesianGrid, + Cell, + Line, + LineChart, + Pie, + PieChart, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis, +} from 'recharts'; +import { exhibitionApi } from '../../api/endpoints'; +import type { ExhibitionDto } from '../../api/types'; +import { ErrorState, Skeleton } from '../../components/ui/States'; +import { homeApi } from './homeApi'; + +/** + * SCR-HOME 요약 차트(소유자 지시 ④) — WISE 대시보드 스타일 Recharts 위젯. + * 신규 백엔드 계약 없이 기존 exhibitionApi.list() + home/hall-centers 데이터에서 파생(경계면 무결). + * 3종: ① 전시 상태 도넛 ② 월별 전시 추이 미니 라인 ③ 전시장별 행사 수 바. + */ + +const TODAY = new Date(); +function ymd(d: Date): string { + return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; +} +const TODAY_YMD = ymd(TODAY); + +type Status = 'ongoing' | 'upcoming' | 'ended'; +function statusOf(start: string, end: string): Status { + if (end < TODAY_YMD) return 'ended'; + if (start > TODAY_YMD) return 'upcoming'; + return 'ongoing'; +} +function matchesCenter(hallLabel: string | null | undefined, code: string): boolean { + if (!hallLabel) return false; + return new RegExp(`제\\s*${code}\\s*전시장`).test(hallLabel); +} + +const C = { + ongoing: 'var(--color-success)', + upcoming: 'var(--color-primary-600)', + ended: 'var(--color-neutral-500)', + grid: 'var(--color-neutral-200)', + axis: 'var(--color-neutral-500)', + bar: 'var(--color-primary-600)', + line: 'var(--color-ai-accent)', +}; + +export function HomeCharts() { + const { t } = useTranslation(); + const eventsQuery = useQuery({ + queryKey: ['home-charts-events'], + queryFn: () => exhibitionApi.list(), + }); + const centersQuery = useQuery({ + queryKey: ['home-hall-centers'], + queryFn: () => homeApi.hallCenters(), + }); + + const rows: ExhibitionDto[] = eventsQuery.data ?? []; + + // ① 상태 분포 + const statusData = useMemo(() => { + const c = { ongoing: 0, upcoming: 0, ended: 0 }; + rows.forEach((e) => { + c[statusOf(e.startDate, e.endDate)] += 1; + }); + return [ + { key: 'ongoing', name: t('home.calendar.legendOngoing'), value: c.ongoing, color: C.ongoing }, + { key: 'upcoming', name: t('home.calendar.legendUpcoming'), value: c.upcoming, color: C.upcoming }, + { key: 'ended', name: t('home.calendar.legendEnded'), value: c.ended, color: C.ended }, + ].filter((d) => d.value > 0); + }, [rows, t]); + + // ② 월별 추이 — 현재 달 기준 -1 ~ +4 (6개월) + const trendData = useMemo(() => { + const base = new Date(TODAY.getFullYear(), TODAY.getMonth() - 1, 1); + const buckets: { ym: string; label: string; count: number }[] = []; + for (let i = 0; i < 6; i++) { + const d = new Date(base.getFullYear(), base.getMonth() + i, 1); + const ym = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`; + buckets.push({ ym, label: `${d.getMonth() + 1}${t('home.charts.monthSuffix')}`, count: 0 }); + } + rows.forEach((e) => { + const ym = (e.startDate ?? '').slice(0, 7); + const b = buckets.find((x) => x.ym === ym); + if (b) b.count += 1; + }); + return buckets; + }, [rows, t]); + + // ③ 전시장별 행사 수 + const centerData = useMemo(() => { + const centers = centersQuery.data ?? []; + return centers.map((c) => ({ + name: c.label, + count: rows.filter((e) => matchesCenter(e.hallLabel, c.code)).length, + })); + }, [rows, centersQuery.data]); + + const loading = eventsQuery.isLoading; + const error = eventsQuery.isError; + + return ( +
+
+

{t('home.charts.title')}

+
+ + {loading ? ( +
+ {Array.from({ length: 3 }).map((_, i) => ( + + ))} +
+ ) : error ? ( + eventsQuery.refetch()} /> + ) : ( +
+ {/* ① 상태 도넛 */} +
+
{t('home.charts.statusTitle')}
+ {statusData.length === 0 ? ( +

{t('home.charts.empty')}

+ ) : ( + + + + {statusData.map((d) => ( + + ))} + + + + + )} +
+ {statusData.map((d) => ( + + + {d.name} {d.value} + + ))} +
+
+ + {/* ② 월별 추이 미니 라인 */} +
+
{t('home.charts.trendTitle')}
+ + + + + + + + + +
+ + {/* ③ 전시장별 바 */} +
+
{t('home.charts.centerTitle')}
+ {centerData.length === 0 ? ( +

{t('home.charts.empty')}

+ ) : ( + + + + + + + + + + )} +
+
+ )} +
+ ); +} diff --git a/src/frontend/src/screens/home/HomePage.tsx b/src/frontend/src/screens/home/HomePage.tsx index 4e46c6e..fcb5714 100644 --- a/src/frontend/src/screens/home/HomePage.tsx +++ b/src/frontend/src/screens/home/HomePage.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState, type FormEvent } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; @@ -6,10 +6,11 @@ import { useAuthStore } from '../../store/authStore'; import { useResolvedEventId } from '../../hooks/useResolvedEventId'; import { exhibitionApi, loginSlideApi, noticeApi, notificationApi } from '../../api/endpoints'; import type { ExhibitionDto } from '../../api/types'; -import { DdayChip } from '../../components/ui/Badge'; +import { AiLabel, DdayChip } from '../../components/ui/Badge'; import { Button } from '../../components/ui/Button'; import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States'; import { + IconAiBot, IconBell, IconCheckCircle, IconChevronLeft, @@ -19,6 +20,7 @@ import { IconFloorplan, IconSearch, IconSettlement, + IconSpark, } from '../../components/ui/icons'; import { homeApi, @@ -33,6 +35,7 @@ import { type CalEvent, type CalStatus, } from './homeCalendar'; +import { HomeCharts } from './HomeCharts'; import './home.css'; /** 오늘(로컬) — 캘린더 강조·상태 파생 기준. 서버 D-day 는 각 API 가 별도 계산. */ @@ -81,6 +84,12 @@ export function HomePage() { + {/* ①-b 요약 차트 (KPI 아래, Recharts) */} + + + {/* ①-c KINTEX AI 어시스턴트 허브 (KPI 아래·배너 위 — AI 기능 홍보 스트립) */} + + {/* ② 배너 캐러셀 */} @@ -183,6 +192,107 @@ function KpiStrip({ name, dateLabel }: { name: string; dateLabel: string }) { ); } +/* ──────────────────────────────────────────────────────────── + * ①-c KINTEX AI 어시스턴트 허브 (AI 기능 홍보 스트립) + * - 5개 AI 도구 카드(실 라우트) + 자연어 질문 퀵 입력(?q= 전달) + * - 행사 스코프가 필요한 카드(배치·갤러리)는 첫 워크스페이스 eventId 계산, + * 없으면 /schedule 로 안내(QuickActions editor 패턴 정합). + * ──────────────────────────────────────────────────────────── */ +const AI_DEFAULT_HALL = 'H7'; // LayoutComparisonPage 기본 홀과 정합 +const AI_DEFAULT_BOOTH = 'A-102'; // ExhibitorHome/Gallery 기본 부스와 정합(갤러리는 샘플 폴백) + +interface AiTool { + key: 'layout' | 'gallery' | 'nlquery' | 'rules' | 'leads'; + Icon: typeof IconSpark; + go: () => void; +} + +function AiHubStrip() { + const { t } = useTranslation(); + const navigate = useNavigate(); + const eventId = useResolvedEventId(); + const [question, setQuestion] = useState(''); + + const tools: AiTool[] = [ + { + key: 'layout', + Icon: IconSpark, + go: () => + navigate(eventId ? `/events/${eventId}/halls/${AI_DEFAULT_HALL}/comparison` : '/schedule'), + }, + { + key: 'gallery', + Icon: IconSpark, + go: () => + navigate(eventId ? `/events/${eventId}/booths/${AI_DEFAULT_BOOTH}/gallery` : '/schedule'), + }, + { key: 'nlquery', Icon: IconAiBot, go: () => navigate('/analytics?tab=nlquery') }, + { key: 'rules', Icon: IconAiBot, go: () => navigate('/analytics?tab=rules') }, + { key: 'leads', Icon: IconSpark, go: () => navigate('/leads') }, + ]; + + function askSubmit(e: FormEvent) { + e.preventDefault(); + const q = question.trim(); + navigate(q ? `/analytics?q=${encodeURIComponent(q)}` : '/analytics'); + } + + return ( +
+
+ +
+

+ {t('home.ai.title')} + {t('home.ai.badge')} +

+

{t('home.ai.subtitle')}

+
+
+ setQuestion(e.target.value)} + placeholder={t('home.ai.askPh')} + aria-label={t('home.ai.askAria')} + /> + +
+
+ +
+ {tools.map((tool) => ( + + ))} +
+
+ ); +} + /* ──────────────────────────────────────────────────────────── * ② 배너 캐러셀 (login-slides 재사용, 220~260px) * ──────────────────────────────────────────────────────────── */ diff --git a/src/frontend/src/screens/home/home.css b/src/frontend/src/screens/home/home.css index f87c3d6..e1077a6 100644 --- a/src/frontend/src/screens/home/home.css +++ b/src/frontend/src/screens/home/home.css @@ -1024,3 +1024,239 @@ grid-template-columns: repeat(3, 1fr); } } + +/* ── ①-b 요약 차트 (Recharts, KPI 아래) ── */ +.kx-home__charts { + padding: var(--space-4); +} +.kx-home__charts-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-4); +} +.kx-home__chart { + margin: 0; + min-width: 0; + border: var(--border-card); + border-radius: var(--radius-lg); + padding: var(--space-3); + background: var(--color-white); + display: flex; + flex-direction: column; +} +.kx-home__chart-cap { + font-size: var(--fs-caption); + font-weight: 700; + color: var(--color-neutral-700); + margin-bottom: var(--space-2); +} +.kx-home__chart-empty { + display: flex; + align-items: center; + justify-content: center; + height: 150px; + font-size: var(--fs-caption); + color: var(--color-neutral-500); +} +.kx-home__chart-legend { + display: flex; + flex-wrap: wrap; + gap: var(--space-1) var(--space-3); + margin-top: var(--space-2); + font-size: var(--fs-caption); + color: var(--color-neutral-500); +} +.kx-home__chart-legend-item { + display: inline-flex; + align-items: center; + gap: 5px; +} +.kx-home__chart-legend-item i { + width: 8px; + height: 8px; + border-radius: 2px; + display: inline-block; +} +.kx-home__chart-legend-item b { + color: var(--color-neutral-900); + font-weight: 700; +} + +@media (max-width: 1100px) { + .kx-home__charts-grid { + grid-template-columns: 1fr; + } +} +@media (min-width: 1101px) and (max-width: 1280px) { + .kx-home__charts-grid { + grid-template-columns: repeat(3, 1fr); + } +} + +/* ──────────────────────────────────────────────────────────── + * ①-c KINTEX AI 어시스턴트 허브 (AI 홍보 스트립) — 밀도 원칙: 높이 과대 금지(~160px) + * 보라 계열 AI 서피스 배경 + 5개 도구 카드(실 라우트) + 자연어 퀵 입력. + * ──────────────────────────────────────────────────────────── */ +.kx-home__aihub { + border: 1px solid var(--color-ai-accent); + border-left: var(--accent-ai); + border-radius: var(--radius-lg); + background: + linear-gradient( + 135deg, + color-mix(in srgb, var(--color-ai-accent) 12%, var(--color-ai-surface)) 0%, + var(--color-ai-surface) 62% + ); + padding: var(--space-4); + display: flex; + flex-direction: column; + gap: var(--space-3); +} + +.kx-home__aihub-head { + display: flex; + align-items: center; + gap: var(--space-3); + flex-wrap: wrap; +} +.kx-home__aihub-badgeicon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + border-radius: var(--radius-sm); + background: var(--color-ai-accent); + color: var(--color-white); + flex: 0 0 auto; +} +.kx-home__aihub-heading { + min-width: 0; + flex: 1 1 auto; +} +.kx-home__aihub-title { + display: flex; + align-items: center; + gap: var(--space-2); + margin: 0; + font-size: var(--fs-h3); + font-weight: 800; + color: var(--color-ai-accent-strong); + letter-spacing: -0.01em; +} +.kx-home__aihub-sub { + margin: 2px 0 0; + font-size: var(--fs-caption); + color: var(--color-neutral-700); +} +.kx-home__aihub-ask { + display: flex; + align-items: center; + gap: var(--space-2); + flex: 0 0 auto; +} +.kx-home__aihub-input { + width: 260px; + max-width: 42vw; + height: 36px; + padding: 0 var(--space-3); + border: 1px solid var(--color-ai-accent); + border-radius: var(--radius-pill); + background: var(--color-white); + color: var(--color-neutral-900); + font-size: var(--fs-caption); +} +.kx-home__aihub-input::placeholder { + color: var(--color-neutral-500); +} +.kx-home__aihub-input:focus-visible { + outline: 2px solid var(--color-ai-accent-strong); + outline-offset: 1px; +} + +.kx-home__aihub-grid { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: var(--space-2); +} +.kx-home__aihub-card { + display: flex; + align-items: flex-start; + gap: var(--space-2); + text-align: left; + padding: var(--space-3); + border: 1px solid var(--border-card); + border-radius: var(--radius-sm); + background: var(--color-white); + cursor: pointer; + transition: transform 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease; +} +.kx-home__aihub-card:hover { + transform: translateY(-2px); + border-color: var(--color-ai-accent); + box-shadow: var(--shadow-level2); +} +.kx-home__aihub-card:focus-visible { + outline: 2px solid var(--color-ai-accent-strong); + outline-offset: 2px; +} +.kx-home__aihub-card-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 30px; + height: 30px; + border-radius: var(--radius-sm); + background: var(--color-ai-surface); + color: var(--color-ai-accent-strong); + flex: 0 0 auto; +} +.kx-home__aihub-card-main { + min-width: 0; + display: flex; + flex-direction: column; + gap: 2px; +} +.kx-home__aihub-card-title { + display: flex; + align-items: center; + gap: var(--space-1); + font-size: var(--fs-caption); + font-weight: 700; + color: var(--color-neutral-900); + line-height: 1.25; +} +.kx-home__aihub-card-tag { + flex: 0 0 auto; + font-size: 10px; + font-weight: 800; + letter-spacing: 0.04em; + padding: 1px 5px; + border-radius: var(--radius-pill); + background: var(--color-ai-accent); + color: var(--color-white); +} +.kx-home__aihub-card-desc { + font-size: var(--fs-caption); + color: var(--color-neutral-500); + line-height: 1.3; +} + +@media (max-width: 1100px) { + .kx-home__aihub-grid { + grid-template-columns: repeat(2, 1fr); + } + .kx-home__aihub-ask { + flex: 1 1 100%; + } + .kx-home__aihub-input { + flex: 1 1 auto; + max-width: none; + width: auto; + } +} +@media (min-width: 1101px) and (max-width: 1280px) { + .kx-home__aihub-grid { + grid-template-columns: repeat(3, 1fr); + } +} diff --git a/src/frontend/src/screens/login/LoginPage.tsx b/src/frontend/src/screens/login/LoginPage.tsx index 53f9c86..a618ec6 100644 --- a/src/frontend/src/screens/login/LoginPage.tsx +++ b/src/frontend/src/screens/login/LoginPage.tsx @@ -136,6 +136,7 @@ export function LoginPage() { /> {t('common.appSuffix')}
+

{t('login.prodTagline')}

{t('login.title')}

{t('login.sub')}

diff --git a/src/frontend/src/screens/login/login.css b/src/frontend/src/screens/login/login.css index d285eb0..584c85c 100644 --- a/src/frontend/src/screens/login/login.css +++ b/src/frontend/src/screens/login/login.css @@ -175,6 +175,13 @@ padding-left: 10px; margin-left: 4px; } +.kx-login__prod { + font-size: var(--fs-body); + line-height: var(--lh-body); + color: var(--color-neutral-500); + text-align: center; + margin: -8px 0 0; +} .kx-login__title { font-size: var(--fs-h1); line-height: var(--lh-h1); diff --git a/src/frontend/src/screens/marketing/EdmCampaignPage.tsx b/src/frontend/src/screens/marketing/EdmCampaignPage.tsx index cd1bcc0..40d9ac9 100644 --- a/src/frontend/src/screens/marketing/EdmCampaignPage.tsx +++ b/src/frontend/src/screens/marketing/EdmCampaignPage.tsx @@ -1,4 +1,5 @@ import { useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { AiLabel } from '../../components/ui/Badge'; import { Button } from '../../components/ui/Button'; @@ -17,6 +18,7 @@ import './marketing.css'; * ★ 정보통신망법 수신동의·수신거부 준수 표기 상시 노출. 세그먼트 규모는 집계 힌트(관람객 PII 미포함). */ export function EdmCampaignPage() { + const { t } = useTranslation(); const eventId = useResolvedEventId(); const queryClient = useQueryClient(); const [filter, setFilter] = useState<'all' | 'active' | 'done'>('all'); @@ -48,6 +50,30 @@ export function EdmCampaignPage() { }, }); + const [sendMsg, setSendMsg] = useState(null); + const sendMut = useMutation({ + mutationFn: (id: string) => marketingApi.sendCampaign(eventId as string, id), + onSuccess: (res) => { + const n = res.sentCount.toLocaleString(); + setSendMsg( + res.mailEnabled + ? t('marketing.sentDone', { n }) + : t('marketing.sentDisabled', { n }), + ); + queryClient.invalidateQueries({ queryKey: ['campaigns', eventId] }); + }, + onError: () => setSendMsg(t('marketing.sendFail')), + }); + + function confirmSend(c: CampaignDto) { + if (sendMut.isPending) return; + const ok = window.confirm(t('marketing.confirm', { name: c.name })); + if (ok) { + setSendMsg(null); + sendMut.mutate(c.id); + } + } + const audience = useMemo( () => SEGMENTS.filter((s) => segments[s.id]).reduce((sum, s) => sum + s.count, 0), [segments], @@ -129,6 +155,12 @@ export function EdmCampaignPage() {
)} + {sendMsg && ( +
+ {sendMsg} +
+ )} +
{/* 캠페인 리스트 */}
@@ -150,7 +182,12 @@ export function EdmCampaignPage() {
    {rows.map((c) => ( - + confirmSend(c)} + sending={sendMut.isPending && sendMut.variables === c.id} + /> ))} {rows.length === 0 && (
  • @@ -275,8 +312,19 @@ export function EdmCampaignPage() { ); } -function CampaignRow({ campaign: c }: { campaign: CampaignDto }) { +function CampaignRow({ + campaign: c, + onSend, + sending, +}: { + campaign: CampaignDto; + onSend?: () => void; + sending?: boolean; +}) { + const { t } = useTranslation(); const status = normalizeStatus(c.status); + // 발송 가능 상태 = 초안·예약(발송중·완료는 불가). 봉인/중복 발송 방지는 서버가 최종 강제. + const canSend = status === 'draft' || status === 'scheduled'; return (
  • @@ -304,6 +352,11 @@ function CampaignRow({ campaign: c }: { campaign: CampaignDto }) { 클릭율 {c.clickRate ?? '-'}
    + {canSend && onSend && ( + + )}
); diff --git a/src/frontend/src/screens/marketing/marketing.css b/src/frontend/src/screens/marketing/marketing.css index 4a4e043..70090f7 100644 --- a/src/frontend/src/screens/marketing/marketing.css +++ b/src/frontend/src/screens/marketing/marketing.css @@ -706,3 +706,13 @@ align-items: flex-start; } } + +/* 캠페인 발송 결과 안내(수신동의자 한정 발송 후) */ +.kx-mkt__send-msg { + padding: 12px 16px; + border-radius: 10px; + background: var(--kx-success-bg, #ecfdf5); + color: var(--kx-success-fg, #065f46); + border: 1px solid var(--kx-success-border, #a7f3d0); + font-size: 14px; +} diff --git a/src/frontend/src/screens/marketing/marketingApi.ts b/src/frontend/src/screens/marketing/marketingApi.ts index 4e2050a..f46e17e 100644 --- a/src/frontend/src/screens/marketing/marketingApi.ts +++ b/src/frontend/src/screens/marketing/marketingApi.ts @@ -4,7 +4,8 @@ * * 백엔드 컨트롤러 정본: * GET /api/events/{eventId}/campaigns?status → ApiResponse - * POST /api/events/{eventId}/campaigns (발송 미구현 — status 전이만) + * POST /api/events/{eventId}/campaigns (생성 — status 전이만) + * POST /api/events/{eventId}/campaigns/{id}/send (수신동의자 한정 실 발송) * GET /api/events/{eventId}/sponsorship → ApiResponse */ import { api } from '../../api/client'; @@ -64,6 +65,15 @@ export interface SponsorshipViewDto { sponsors: SponsorDto[]; } +// ── 캠페인 발송 결과 ── +export interface CampaignSendResultDto { + id: string; + status: string; // done + sentCount: number; + mailEnabled: boolean; + meta: string; +} + export const marketingApi = { campaigns: (eventId: string, status?: string) => { const qs = status ? `?status=${encodeURIComponent(status)}` : ''; @@ -71,6 +81,11 @@ export const marketingApi = { }, createCampaign: (eventId: string, body: CampaignCreateBody) => api.post(`/api/events/${encodeURIComponent(eventId)}/campaigns`, body), + sendCampaign: (eventId: string, id: string) => + api.post( + `/api/events/${encodeURIComponent(eventId)}/campaigns/${encodeURIComponent(id)}/send`, + {}, + ), sponsorship: (eventId: string) => api.get(`/api/events/${encodeURIComponent(eventId)}/sponsorship`), }; diff --git a/src/frontend/src/screens/public/PublicHomePage.tsx b/src/frontend/src/screens/public/PublicHomePage.tsx index 3e065d1..d7aefed 100644 --- a/src/frontend/src/screens/public/PublicHomePage.tsx +++ b/src/frontend/src/screens/public/PublicHomePage.tsx @@ -14,12 +14,20 @@ import { IconCalendar, IconPin, IconArrowRight, + IconChevronRight, IconTrain, IconBus, IconParking, IconShuttle, IconMap, + IconVenue, + IconBuyer, + IconFactory, + IconQr, + IconRobot, + IconTarget, } from './publicIcons'; +import type { ComponentType, SVGProps } from 'react'; function ddayClass(d: number) { if (d <= 3) return 'kxp-dday kxp-dday--soon'; @@ -27,6 +35,29 @@ function ddayClass(d: number) { return 'kxp-dday'; } +type Ico = ComponentType>; + +/** P1 제품 아이덴티티 — 역할별 가치 카드 4종(주최자·참가업체·공사업체·관람객). */ +const ROLE_CARDS: { + key: string; + icon: Ico; + /** 진입 CTA 목적지(로그인 또는 사전등록). */ + to: string; +}[] = [ + { key: 'organizer', icon: IconVenue, to: '/login' }, + { key: 'exhibitor', icon: IconBuyer, to: '/login' }, + { key: 'contractor', icon: IconFactory, to: '/login' }, + { key: 'visitor', icon: IconQr, to: '#events' }, +]; + +/** P1 핵심 기능 스텝(과장 없이 실기능만): AI 배치 → 나노바나나 시안 → 역경매 옥션 → 실시간 정산. */ +const FEATURE_STEPS: { key: string; icon: Ico }[] = [ + { key: 'layout', icon: IconRobot }, + { key: 'render', icon: IconSparkles }, + { key: 'auction', icon: IconFactory }, + { key: 'settle', icon: IconTarget }, +]; + /** 진행중·예정 우선 정렬 후 상위 N건만 홈에 노출. */ function pickFeatured(events: PublicEvent[], max = 6): PublicEvent[] { const rank = (e: PublicEvent) => { @@ -82,26 +113,95 @@ export function PublicHomePage() { + {/* 제품 소개 — 역할별 가치 카드 4장 (제품 아이덴티티) */} +
+
+
+
+

{t('home.roleTitle')}

+

{t('home.roleSub')}

+
+
+ +
+ {ROLE_CARDS.map(({ key, icon: Icon, to }) => { + const cta = ( + + {t(`home.roleCard.${key}.cta`)} + + ); + return ( +
+ + + + {t(`home.roleCard.${key}.badge`)} +

{t(`home.roleCard.${key}.title`)}

+

{t(`home.roleCard.${key}.desc`)}

+ {to.startsWith('#') ? ( + + {cta} + + ) : ( + + {cta} + + )} +
+ ); + })} +
+
+
+ + {/* 핵심 기능 스트립 — AI 배치 → 시공 시안 → 역경매 옥션 → 실시간 정산 */} +
+
+
+
+

{t('home.stepsTitle')}

+

{t('home.stepsSub')}

+
+
+ +
    + {FEATURE_STEPS.map(({ key, icon: Icon }, i) => ( +
  1. +
    + + + + {i + 1} +

    {t(`home.featStep.${key}.title`)}

    +

    {t(`home.featStep.${key}.desc`)}

    +
    + {i < FEATURE_STEPS.length - 1 && ( + + + + )} +
  2. + ))} +
+
+
+ {/* 진행/예정 행사 */}
diff --git a/src/frontend/src/screens/public/PublicShell.tsx b/src/frontend/src/screens/public/PublicShell.tsx index 3f55e4c..187c79f 100644 --- a/src/frontend/src/screens/public/PublicShell.tsx +++ b/src/frontend/src/screens/public/PublicShell.tsx @@ -4,6 +4,7 @@ */ import { useState, type ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; +import { Link } from 'react-router-dom'; import { IconMenu, IconClose, IconSearch } from './publicIcons'; import { LanguageSwitcher } from '../../components/ui/LanguageSwitcher'; import './public.css'; @@ -75,6 +76,10 @@ export function PublicShell({ + + {t('shell.login')} + + {ctaLabel} @@ -98,6 +103,9 @@ export function PublicShell({ {t(it.i18n)} ))} + + {t('shell.login')} + {ctaLabel} diff --git a/src/frontend/src/screens/public/public.css b/src/frontend/src/screens/public/public.css index a3107d6..0a297df 100644 --- a/src/frontend/src/screens/public/public.css +++ b/src/frontend/src/screens/public/public.css @@ -324,6 +324,9 @@ .kxp-header__cta { display: none; } +.kxp-header__login { + display: none; +} .kxp-header__burger { display: inline-flex; align-items: center; @@ -377,6 +380,9 @@ .kxp-header__cta { display: inline-flex; } + .kxp-header__login { + display: inline-flex; + } } /* ═══ 메인 ═══ */ @@ -539,6 +545,163 @@ } } +/* ═══ 제품 역할 가치 카드(P1 제품 아이덴티티) ═══ */ +.kxp-roles { + display: grid; + grid-template-columns: 1fr; + gap: 16px; +} +@media (min-width: 640px) { + .kxp-roles { + grid-template-columns: repeat(2, 1fr); + } +} +@media (min-width: 1024px) { + .kxp-roles { + grid-template-columns: repeat(4, 1fr); + } +} +.kxp-role { + display: flex; + flex-direction: column; + gap: 12px; + padding: 24px; + background: var(--color-white); + border: var(--border-card); + border-radius: var(--radius-lg); + transition: box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease; +} +.kxp-role:hover { + border-color: var(--color-primary-600); + box-shadow: var(--shadow-level2); + transform: translateY(-2px); +} +.kxp-role__ic { + width: 48px; + height: 48px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-lg); + background: var(--color-primary-050); + color: var(--color-primary-600); +} +.kxp-role__badge { + font-size: var(--fs-caption); + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; + color: var(--color-primary-600); +} +.kxp-role__title { + font-size: var(--fs-h2); + font-weight: 800; + color: var(--color-neutral-900); + letter-spacing: -0.01em; + margin: 0; +} +.kxp-role__desc { + font-size: var(--fs-body); + line-height: var(--lh-body); + color: var(--color-neutral-500); + margin: 0; + flex: 1; +} +.kxp-role__link { + text-decoration: none; +} +.kxp-role__cta { + display: inline-flex; + align-items: center; + gap: 4px; + font-size: var(--fs-body); + font-weight: 700; + color: var(--color-primary-600); +} +.kxp-role__link:hover .kxp-role__cta { + text-decoration: underline; +} + +/* ═══ 핵심 기능 스텝 스트립(P1) ═══ */ +.kxp-steps { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: 1fr; + gap: 16px; +} +@media (min-width: 1024px) { + .kxp-steps { + grid-template-columns: repeat(4, 1fr); + align-items: stretch; + } +} +.kxp-step { + position: relative; + display: flex; + flex-direction: column; +} +.kxp-step__card { + position: relative; + display: flex; + flex-direction: column; + gap: 10px; + height: 100%; + padding: 24px 20px; + background: var(--color-white); + border: var(--border-card); + border-radius: var(--radius-lg); +} +.kxp-step__ic { + width: 44px; + height: 44px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-lg); + background: var(--color-primary-050); + color: var(--color-primary-600); +} +.kxp-step__no { + position: absolute; + top: 16px; + right: 18px; + font-size: var(--fs-h1); + font-weight: 800; + line-height: 1; + color: var(--color-neutral-100); +} +.kxp-step__title { + font-size: var(--fs-h3); + font-weight: 800; + color: var(--color-neutral-900); + margin: 0; +} +.kxp-step__desc { + font-size: var(--fs-body); + line-height: var(--lh-body); + color: var(--color-neutral-500); + margin: 0; +} +.kxp-step__arrow { + display: flex; + align-items: center; + justify-content: center; + color: var(--color-neutral-500); + padding: 8px 0; +} +@media (min-width: 1024px) { + .kxp-step__arrow { + position: absolute; + top: 50%; + right: -14px; + transform: translateY(-50%); + padding: 0; + z-index: 1; + } +} + /* ═══ 이벤트 카드 그리드(P1) ═══ */ .kxp-eventgrid { display: grid; diff --git a/src/frontend/src/store/uiStore.ts b/src/frontend/src/store/uiStore.ts new file mode 100644 index 0000000..c364217 --- /dev/null +++ b/src/frontend/src/store/uiStore.ts @@ -0,0 +1,61 @@ +/* + * 셸 UI 상태 (zustand) — 사이드바 접힘(navCollapsed) 토글 + localStorage 지속. + * WISE(UIWS) uiStore 패턴 이식: 상단 Header 햄버거(nav-toggle)가 toggleNav 로 사이드바를 접고, + * 데스크톱=사이드바 숨김(콘텐츠 전폭), <1024px=오버레이 드로어(+백드롭). themeStore 와 동일한 + * 지속·스탬프 관례를 따른다(신규 store 최소 표면). + */ +import { create } from 'zustand'; + +const STORAGE_KEY = 'kx-nav-collapsed'; +const MOBILE_QUERY = '(max-width: 1024px)'; + +/** + * 초기 접힘 상태 — 저장값 우선, 없으면 뷰포트로 추정(모바일이면 접힘=드로어 닫힘 기본). + * 모바일에서 저장값 없이 열린 채 첫 렌더되어 드로어가 화면을 덮는 회귀를 방지한다. + */ +function readInitial(): boolean { + if (typeof localStorage !== 'undefined') { + const v = localStorage.getItem(STORAGE_KEY); + if (v === 'true') return true; + if (v === 'false') return false; + } + if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') { + return window.matchMedia(MOBILE_QUERY).matches; + } + return false; +} + +interface UiState { + /** 사이드바 접힘 여부. true=접힘(데스크톱 숨김 / 모바일 드로어 닫힘). */ + navCollapsed: boolean; + /** 명시 설정 — 지속. */ + setNavCollapsed: (v: boolean) => void; + /** 햄버거 토글. */ + toggleNav: () => void; +} + +function persist(v: boolean) { + if (typeof localStorage !== 'undefined') localStorage.setItem(STORAGE_KEY, String(v)); +} + +export const useUiStore = create((set, get) => ({ + navCollapsed: readInitial(), + setNavCollapsed: (v) => { + persist(v); + set({ navCollapsed: v }); + }, + toggleNav: () => { + const next = !get().navCollapsed; + persist(next); + set({ navCollapsed: next }); + }, +})); + +/** <1024px 여부(모바일 드로어 판정용). SSR 안전. */ +export function isMobileViewport(): boolean { + return ( + typeof window !== 'undefined' && + typeof window.matchMedia === 'function' && + window.matchMedia(MOBILE_QUERY).matches + ); +}