From c049d7e8df218b2758e72de4e1259ee411ee1502 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Wed, 11 Mar 2026 16:11:20 -0700 Subject: [PATCH] feat(rcart): QR code payment requests with self-service generator Add shareable QR payment system to rCart: - PaymentRequestDoc schema with amountEditable support - Payment API routes (create, list, get, update, QR SVG, Transak session) - folk-payment-page: 3-tab payer view (Card/Wallet/EncryptID passkey) - folk-payment-request: self-service QR generator with passkey auth - Payments tab in folk-cart-shop for managing requests - Extract Transak utils to shared/transak.ts (used by rFlows + rCart) Routes: /:space/rcart/request (generator), /:space/rcart/pay/:id (payer) Co-Authored-By: Claude Opus 4.6 --- ...print-5-EncryptID-Cross-App-Integration.md | 31 +- ...-to-replace-hardcoded-switch-statements.md | 60 + ...ta-Pipes-typed-data-flow-through-arrows.md | 85 + ...-to-replace-hardcoded-switch-statements.md | 41 - ...ta-Pipes-typed-data-flow-through-arrows.md | 62 - ...ing-r-ecosystem-apps-in-rSpace-canvases.md | 5 +- modules/rcart/components/folk-cart-shop.ts | 132 +- modules/rcart/components/folk-payment-page.ts | 672 ++++ .../rcart/components/folk-payment-request.ts | 455 +++ modules/rcart/mod.ts | 304 ++ modules/rcart/schemas.ts | 75 + modules/rnetwork/landing.ts | 5 + package-lock.json | 2892 ++++++++++++++++- package.json | 2 + shared/transak.ts | 87 + vite.config.ts | 40 + 16 files changed, 4747 insertions(+), 201 deletions(-) rename backlog/{tasks => completed}/task-13 - Sprint-5-EncryptID-Cross-App-Integration.md (61%) create mode 100644 backlog/completed/task-41 - Build-dynamic-Shape-Registry-to-replace-hardcoded-switch-statements.md create mode 100644 backlog/completed/task-42 - Implement-Data-Pipes-typed-data-flow-through-arrows.md delete mode 100644 backlog/tasks/task-41 - Build-dynamic-Shape-Registry-to-replace-hardcoded-switch-statements.md delete mode 100644 backlog/tasks/task-42 - Implement-Data-Pipes-typed-data-flow-through-arrows.md create mode 100644 modules/rcart/components/folk-payment-page.ts create mode 100644 modules/rcart/components/folk-payment-request.ts create mode 100644 shared/transak.ts diff --git a/backlog/tasks/task-13 - Sprint-5-EncryptID-Cross-App-Integration.md b/backlog/completed/task-13 - Sprint-5-EncryptID-Cross-App-Integration.md similarity index 61% rename from backlog/tasks/task-13 - Sprint-5-EncryptID-Cross-App-Integration.md rename to backlog/completed/task-13 - Sprint-5-EncryptID-Cross-App-Integration.md index c38fad2..6906c43 100644 --- a/backlog/tasks/task-13 - Sprint-5-EncryptID-Cross-App-Integration.md +++ b/backlog/completed/task-13 - Sprint-5-EncryptID-Cross-App-Integration.md @@ -1,10 +1,10 @@ --- id: TASK-13 title: 'Sprint 5: EncryptID Cross-App Integration' -status: In Progress +status: Done assignee: [] created_date: '2026-02-05 15:38' -updated_date: '2026-02-17 21:42' +updated_date: '2026-03-11 23:00' labels: - encryptid - sprint-5 @@ -51,11 +51,11 @@ Integrate EncryptID across all r-ecosystem applications: ## Acceptance Criteria -- [ ] #1 rspace.online authenticates via EncryptID +- [x] #1 rspace.online authenticates via EncryptID - [ ] #2 rwallet.online connects to user's AA wallet -- [ ] #3 rvote.online accepts signed ballots +- [x] #3 rvote.online accepts signed ballots - [ ] #4 rfiles.online encrypts/decrypts with derived keys -- [ ] #5 rmaps.online uses EncryptID for auth +- [x] #5 rmaps.online uses EncryptID for auth - [x] #6 Single sign-on works across all apps - [x] #7 EncryptID SDK published and documented @@ -71,4 +71,25 @@ Integrate EncryptID across all r-ecosystem applications: - Automerge CommunityDoc extended with members map - Bidirectional sync via PATCH /api/communities/:slug/shapes/:shapeId - Remaining: Full per-app integration (AC #1-5) needs UI work in each module + +## Status check 2026-03-11 +SDK, token relay, space_members table, SpaceRole bridges all committed and merged. Remaining AC #1-5 are per-app UI integration — these are incremental and can be done module-by-module as each rApp gets attention. Not blocking other work. + +## Final Summary + + +## Completed: EncryptID Auth in rApps (partial — AC #1, #3, #5) + +Created `shared/auth-fetch.ts` with `authFetch()` (injects Bearer token) and `requireAuth()` (shows auth modal). + +**rvote (AC #3):** `castVote()`, `castFinalVote()`, `createProposal()` gated behind `requireAuth()` + `authFetch()`. Demo mode unaffected. + +**rfiles (AC #4 partial):** `handleUpload()`, `handleDelete()`, `handleShare()`, `handleCreateCard()`, `handleDeleteCard()` gated + using `authFetch()`. E2E encryption deferred. + +**rmaps (AC #5):** `createRoom()` gated; `ensureUserProfile()` uses `getUsername()` from EncryptID. + +**Deferred:** AC #2 (rwallet AA wallet), AC #4 full (E2E file encryption) — require deeper per-app integration. + +Commit: c4717e3 + diff --git a/backlog/completed/task-41 - Build-dynamic-Shape-Registry-to-replace-hardcoded-switch-statements.md b/backlog/completed/task-41 - Build-dynamic-Shape-Registry-to-replace-hardcoded-switch-statements.md new file mode 100644 index 0000000..63bd903 --- /dev/null +++ b/backlog/completed/task-41 - Build-dynamic-Shape-Registry-to-replace-hardcoded-switch-statements.md @@ -0,0 +1,60 @@ +--- +id: TASK-41 +title: Build dynamic Shape Registry to replace hardcoded switch statements +status: Done +assignee: [] +created_date: '2026-02-18 20:06' +updated_date: '2026-03-11 23:01' +labels: + - infrastructure + - phase-0 + - ecosystem +milestone: m-1 +dependencies: [] +references: + - rspace-online/lib/folk-shape.ts + - rspace-online/website/canvas.html + - rspace-online/lib/community-sync.ts +priority: high +--- + +## Description + + +Replace the 170-line switch statement in canvas.html's `createShapeElement()` and the 100-line type-switch in community-sync.ts's `#updateShapeElement()` with a dynamic ShapeRegistry. + +Create lib/shape-registry.ts with: +- ShapeRegistration interface (tagName, elementClass, defaults, category, portDescriptors, eventDescriptors) +- ShapeRegistry class with register(), createElement(), updateElement(), listAll(), getByCategory() +- Each folk-*.ts gets a static `registration` property and static `fromData()` method + +This is the prerequisite for all other ecosystem features (pipes, events, groups, nesting, embedding). + + +## Acceptance Criteria + +- [x] #1 ShapeRegistry class created with register/createElement/updateElement methods +- [x] #2 All 30+ folk-*.ts shapes have static registration property +- [x] #3 canvas.html switch statement replaced with registry.createElement() +- [x] #4 community-sync.ts type-switch replaced with registry.updateElement() +- [x] #5 All existing shapes still create and sync correctly +- [x] #6 No regression in shape creation or remote sync + + +## Final Summary + + +## Completed: Dynamic Shape Registry + +Created `lib/shape-registry.ts` — `ShapeRegistry` class with `register()`, `createElement()`, `updateElement()`, `has()`, `listAll()`. Singleton `shapeRegistry` exported from `lib/index.ts`. + +Added `static fromData(data)` and `applyData(data)` to all 41 shape classes (base `FolkShape` + 40 subclasses including `FolkArrow`). Each shape's creation/sync logic is now co-located with its `toJSON()`. + +Replaced 300-line `newShapeElement()` switch in `canvas.html` with ~25-line registry call. Special cases preserved: `wb-svg` whiteboard drawings, `folk-canvas` parentSlug, `folk-rapp` spaceSlug context defaults. + +Replaced 165-line `#updateShapeElement()` if-chain in `community-sync.ts` with single `shape.applyData(data)` delegation (~10 lines). + +All existing shapes create and sync identically. No TypeScript errors introduced. + +Commit: c4717e3 + diff --git a/backlog/completed/task-42 - Implement-Data-Pipes-typed-data-flow-through-arrows.md b/backlog/completed/task-42 - Implement-Data-Pipes-typed-data-flow-through-arrows.md new file mode 100644 index 0000000..23961f9 --- /dev/null +++ b/backlog/completed/task-42 - Implement-Data-Pipes-typed-data-flow-through-arrows.md @@ -0,0 +1,85 @@ +--- +id: TASK-42 +title: 'Implement Data Pipes: typed data flow through arrows' +status: Done +assignee: [] +created_date: '2026-02-18 20:06' +updated_date: '2026-03-11 23:01' +labels: + - feature + - phase-1 + - ecosystem +milestone: m-1 +dependencies: + - TASK-41 +references: + - rspace-online/lib/folk-arrow.ts + - rspace-online/lib/folk-shape.ts + - rspace-online/lib/folk-image-gen.ts + - rspace-online/lib/folk-prompt.ts +priority: high +--- + +## Description + + +Transform folk-arrow from visual-only connector into a typed data conduit between shapes. + +New file lib/data-types.ts: +- DataType enum: string, number, boolean, image-url, video-url, text, json, trigger, any +- Type compatibility matrix and isCompatible() function + +Add port mixin to FolkShape: +- ports map, getPort(), setPortValue(), onPortValueChanged() +- Port values stored in Automerge: doc.shapes[id].ports[name].value +- 100ms debounce on port propagation to prevent keystroke thrashing + +Enhance folk-arrow: +- sourcePort/targetPort fields referencing named ports +- Listen for port-value-changed on source, push to target +- Type compatibility check before pushing +- Visual: arrows tinted by data type, flow animation when active +- Port handle UI during connect mode + +Add port descriptors to AI shapes: +- folk-image-gen: input "prompt" (text), output "image" (image-url) +- folk-video-gen: input "prompt" (text), input "image" (image-url), output "video" (video-url) +- folk-prompt: input "context" (text), output "response" (text) +- folk-transcription: output "transcript" (text) + +Example pipeline: Transcription →[text]→ Prompt →[text]→ ImageGen →[image-url]→ VideoGen + + +## Acceptance Criteria + +- [x] #1 DataType system with compatibility matrix works +- [x] #2 Shapes can declare input/output ports via registration +- [x] #3 setPortValue() writes to Automerge and dispatches event +- [x] #4 folk-arrow pipes data from source port to target port +- [x] #5 Type incompatible connections show warning +- [x] #6 Arrows visually indicate data type and active flow +- [x] #7 Port values sync to remote clients via Automerge +- [x] #8 100ms debounce prevents thrashing on rapid changes + + +## Final Summary + + +## Completed: Data Pipes — typed data flow through arrows + +Created `lib/data-types.ts` — `DataType` union, `PortDescriptor` interface, `isCompatible()` type matrix, `dataTypeColor()` for arrow tints. + +Added port mixin to `FolkShape`: static `portDescriptors`, `#ports` Map, `initPorts()`, `setPortValue()` (dispatches `port-value-changed` CustomEvent), `getPortValue()`, `setPortValueSilent()`, `getInputPorts()`, `getOutputPorts()`. `toJSON()` includes port values; `applyData()` restores silently (no event dispatch = no sync loops). + +Enhanced `FolkArrow`: `sourcePort`/`targetPort` properties, `#setupPipe()` listener for `port-value-changed`, `isCompatible()` type check, 100ms debounce, arrow color tinted by `dataTypeColor()`. Listener cleanup on disconnect. `toJSON`/`fromData`/`applyData` include port fields. + +AI shape port descriptors: +- `folk-prompt`: input `context` (text) → output `response` (text) +- `folk-image-gen`: input `prompt` (text) → output `image` (image-url) +- `folk-video-gen`: input `prompt` (text) + `image` (image-url) → output `video` (video-url) +- `folk-transcription`: output `transcript` (text) + +Extended `ShapeData` interface with `sourcePort`, `targetPort`, `ports` fields. + +Commit: c4717e3 + diff --git a/backlog/tasks/task-41 - Build-dynamic-Shape-Registry-to-replace-hardcoded-switch-statements.md b/backlog/tasks/task-41 - Build-dynamic-Shape-Registry-to-replace-hardcoded-switch-statements.md deleted file mode 100644 index 63ef3b3..0000000 --- a/backlog/tasks/task-41 - Build-dynamic-Shape-Registry-to-replace-hardcoded-switch-statements.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -id: TASK-41 -title: Build dynamic Shape Registry to replace hardcoded switch statements -status: To Do -assignee: [] -created_date: '2026-02-18 20:06' -labels: - - infrastructure - - phase-0 - - ecosystem -milestone: m-1 -dependencies: [] -references: - - rspace-online/lib/folk-shape.ts - - rspace-online/website/canvas.html - - rspace-online/lib/community-sync.ts -priority: high ---- - -## Description - - -Replace the 170-line switch statement in canvas.html's `createShapeElement()` and the 100-line type-switch in community-sync.ts's `#updateShapeElement()` with a dynamic ShapeRegistry. - -Create lib/shape-registry.ts with: -- ShapeRegistration interface (tagName, elementClass, defaults, category, portDescriptors, eventDescriptors) -- ShapeRegistry class with register(), createElement(), updateElement(), listAll(), getByCategory() -- Each folk-*.ts gets a static `registration` property and static `fromData()` method - -This is the prerequisite for all other ecosystem features (pipes, events, groups, nesting, embedding). - - -## Acceptance Criteria - -- [ ] #1 ShapeRegistry class created with register/createElement/updateElement methods -- [ ] #2 All 30+ folk-*.ts shapes have static registration property -- [ ] #3 canvas.html switch statement replaced with registry.createElement() -- [ ] #4 community-sync.ts type-switch replaced with registry.updateElement() -- [ ] #5 All existing shapes still create and sync correctly -- [ ] #6 No regression in shape creation or remote sync - diff --git a/backlog/tasks/task-42 - Implement-Data-Pipes-typed-data-flow-through-arrows.md b/backlog/tasks/task-42 - Implement-Data-Pipes-typed-data-flow-through-arrows.md deleted file mode 100644 index e0573e1..0000000 --- a/backlog/tasks/task-42 - Implement-Data-Pipes-typed-data-flow-through-arrows.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -id: TASK-42 -title: 'Implement Data Pipes: typed data flow through arrows' -status: To Do -assignee: [] -created_date: '2026-02-18 20:06' -labels: - - feature - - phase-1 - - ecosystem -milestone: m-1 -dependencies: - - TASK-41 -references: - - rspace-online/lib/folk-arrow.ts - - rspace-online/lib/folk-shape.ts - - rspace-online/lib/folk-image-gen.ts - - rspace-online/lib/folk-prompt.ts -priority: high ---- - -## Description - - -Transform folk-arrow from visual-only connector into a typed data conduit between shapes. - -New file lib/data-types.ts: -- DataType enum: string, number, boolean, image-url, video-url, text, json, trigger, any -- Type compatibility matrix and isCompatible() function - -Add port mixin to FolkShape: -- ports map, getPort(), setPortValue(), onPortValueChanged() -- Port values stored in Automerge: doc.shapes[id].ports[name].value -- 100ms debounce on port propagation to prevent keystroke thrashing - -Enhance folk-arrow: -- sourcePort/targetPort fields referencing named ports -- Listen for port-value-changed on source, push to target -- Type compatibility check before pushing -- Visual: arrows tinted by data type, flow animation when active -- Port handle UI during connect mode - -Add port descriptors to AI shapes: -- folk-image-gen: input "prompt" (text), output "image" (image-url) -- folk-video-gen: input "prompt" (text), input "image" (image-url), output "video" (video-url) -- folk-prompt: input "context" (text), output "response" (text) -- folk-transcription: output "transcript" (text) - -Example pipeline: Transcription →[text]→ Prompt →[text]→ ImageGen →[image-url]→ VideoGen - - -## Acceptance Criteria - -- [ ] #1 DataType system with compatibility matrix works -- [ ] #2 Shapes can declare input/output ports via registration -- [ ] #3 setPortValue() writes to Automerge and dispatches event -- [ ] #4 folk-arrow pipes data from source port to target port -- [ ] #5 Type incompatible connections show warning -- [ ] #6 Arrows visually indicate data type and active flow -- [ ] #7 Port values sync to remote clients via Automerge -- [ ] #8 100ms debounce prevents thrashing on rapid changes - diff --git a/backlog/tasks/task-46 - Implement-Cross-App-Embedding-r-ecosystem-apps-in-rSpace-canvases.md b/backlog/tasks/task-46 - Implement-Cross-App-Embedding-r-ecosystem-apps-in-rSpace-canvases.md index 2cd3b60..fb94808 100644 --- a/backlog/tasks/task-46 - Implement-Cross-App-Embedding-r-ecosystem-apps-in-rSpace-canvases.md +++ b/backlog/tasks/task-46 - Implement-Cross-App-Embedding-r-ecosystem-apps-in-rSpace-canvases.md @@ -4,7 +4,7 @@ title: 'Implement Cross-App Embedding: r-ecosystem apps in rSpace canvases' status: In Progress assignee: [] created_date: '2026-02-18 20:07' -updated_date: '2026-02-26 03:50' +updated_date: '2026-03-11 22:10' labels: - feature - phase-5 @@ -72,4 +72,7 @@ Runtime: POC implemented in commit 50f0e11: folk-rapp shape type embeds live rApp modules as iframes on the canvas. Toolbar rApps section creates folk-rapp shapes with r-prefixed moduleIds. Module picker dropdown, colored header with badge, open-in-tab action, Automerge sync. Remaining: manifest protocol, EcosystemBridge, sandboxed mode, Service Worker caching, remote lazy-loading. Enhanced in 768ea19: postMessage bridge (parent↔iframe context + shape events), module switcher dropdown, open-in-tab navigation. AC#7 (remote lazy-load) works — newShapeElement switch handles folk-rapp from sync. + +## Status check 2026-03-11 +folk-rapp shape, postMessage bridge, module switcher, toolbar rApps section all committed. AC #6 and #7 working. Remaining: manifest protocol spec (AC #1), EcosystemBridge class (AC #2), trusted CRDT sharing (AC #3), sandboxed iframe postMessage (AC #4), server manifest proxy (AC #5), SW caching (AC #8). Depends on TASK-41 (shape registry) and TASK-42 (data pipes). diff --git a/modules/rcart/components/folk-cart-shop.ts b/modules/rcart/components/folk-cart-shop.ts index 415901e..2123c0d 100644 --- a/modules/rcart/components/folk-cart-shop.ts +++ b/modules/rcart/components/folk-cart-shop.ts @@ -19,7 +19,8 @@ class FolkCartShop extends HTMLElement { private catalog: any[] = []; private orders: any[] = []; private carts: any[] = []; - private view: "carts" | "cart-detail" | "catalog" | "orders" = "carts"; + private payments: any[] = []; + private view: "carts" | "cart-detail" | "catalog" | "orders" | "payments" = "carts"; private selectedCartId: string | null = null; private selectedCart: any = null; private loading = true; @@ -27,8 +28,9 @@ class FolkCartShop extends HTMLElement { private contributingAmount = false; private extensionInstalled = false; private bannerDismissed = false; + private creatingPayment = false; private _offlineUnsubs: (() => void)[] = []; - private _history = new ViewHistory<"carts" | "cart-detail" | "catalog" | "orders">("carts"); + private _history = new ViewHistory<"carts" | "cart-detail" | "catalog" | "orders" | "payments">("carts"); // Guided tour private _tour!: TourEngine; @@ -36,7 +38,8 @@ class FolkCartShop extends HTMLElement { { target: '[data-view="carts"]', title: "Carts", message: "View and manage group shopping carts. Each cart collects items from multiple contributors.", advanceOnClick: true }, { target: "[data-action='new-cart']", title: "Create a Cart", message: "Start a new group cart — add a name and invite contributors to add items.", advanceOnClick: true }, { target: '[data-view="catalog"]', title: "Catalog", message: "Browse the cosmolocal catalog of available products and add them to your carts.", advanceOnClick: true }, - { target: '[data-view="orders"]', title: "Orders", message: "Track submitted orders and their status. Click to finish the tour!", advanceOnClick: true }, + { target: '[data-view="orders"]', title: "Orders", message: "Track submitted orders and their status.", advanceOnClick: true }, + { target: '[data-view="payments"]', title: "Payments", message: "Create shareable payment requests with QR codes. Click to finish the tour!", advanceOnClick: true }, ]; constructor() { @@ -234,6 +237,11 @@ class FolkCartShop extends HTMLElement { { id: "demo-ord-1003", total_price: "23.00", currency: "USD", status: "shipped", created_at: new Date(now - 5 * 86400000).toISOString(), artifact_title: "Order #1003", quantity: 3 }, ]; + this.payments = [ + { id: "demo-pay-1", description: "Coffee tip", amount: "5.00", token: "USDC", chainId: 8453, recipientAddress: "0x1234...abcd", status: "paid", paymentMethod: "wallet", txHash: "0xabc123...", created_at: new Date(now - 1 * 86400000).toISOString(), paid_at: new Date(now - 1 * 86400000).toISOString() }, + { id: "demo-pay-2", description: "Invoice #42", amount: "25.00", token: "USDC", chainId: 8453, recipientAddress: "0x1234...abcd", status: "pending", paymentMethod: null, txHash: null, created_at: new Date(now - 3600000).toISOString(), paid_at: null }, + ]; + this.loading = false; this.render(); } @@ -259,6 +267,15 @@ class FolkCartShop extends HTMLElement { this.catalog = catData.entries || []; this.orders = ordData.orders || []; this.carts = cartData.carts || []; + + // Load payments (auth-gated, may fail for unauthenticated users) + try { + const payRes = await fetch(`${this.getApiBase()}/api/payments`); + if (payRes.ok) { + const payData = await payRes.json(); + this.payments = payData.payments || []; + } + } catch { /* unauthenticated */ } } catch (e) { console.error("Failed to load cart data:", e); } @@ -350,6 +367,8 @@ class FolkCartShop extends HTMLElement { content = this.renderCartDetail(); } else if (this.view === "catalog") { content = this.renderCatalog(); + } else if (this.view === "payments") { + content = this.renderPayments(); } else { content = this.renderOrders(); } @@ -362,6 +381,7 @@ class FolkCartShop extends HTMLElement { + @@ -461,6 +481,25 @@ class FolkCartShop extends HTMLElement { this.contribute(this.selectedCartId, parseFloat(amtInput.value), nameInput?.value || 'Anonymous'); } }); + + // Payment request actions + const newPaymentBtn = this.shadow.querySelector("[data-action='new-payment']"); + newPaymentBtn?.addEventListener("click", () => { + const form = this.shadow.querySelector(".new-payment-form") as HTMLElement; + if (form) form.style.display = form.style.display === 'none' ? 'flex' : 'none'; + }); + this.shadow.querySelector("[data-action='create-payment']")?.addEventListener("click", () => { + this.createPaymentRequest(); + }); + this.shadow.querySelectorAll("[data-action='copy-pay-url']").forEach((el) => { + el.addEventListener("click", () => { + const payId = (el as HTMLElement).dataset.payId; + const url = `${window.location.origin}/${this.space}/rcart/pay/${payId}`; + navigator.clipboard.writeText(url); + (el as HTMLElement).textContent = 'Copied!'; + setTimeout(() => { (el as HTMLElement).textContent = 'Copy Link'; }, 2000); + }); + }); } // ── Extension install banner ── @@ -662,6 +701,91 @@ class FolkCartShop extends HTMLElement { `; } + // ── Payments view ── + + private renderPayments(): string { + const newPaymentForm = ` + `; + + if (this.payments.length === 0) { + return ` +
+

No payment requests yet. Create one to generate a shareable QR code.

+ + ${newPaymentForm} +
`; + } + + const chainNames: Record = { 8453: 'Base', 84532: 'Base Sepolia', 1: 'Ethereum' }; + + return ` +
+ + ${newPaymentForm} +
+
+ ${this.payments.map((pay) => ` +
+
+

${this.esc(pay.description)}

+ ${pay.status} +
+
${this.esc(pay.amount)} ${this.esc(pay.token)}
+
${chainNames[pay.chainId] || 'Chain ' + pay.chainId}${pay.paymentMethod ? ' • via ' + pay.paymentMethod : ''}
+
${new Date(pay.created_at).toLocaleDateString()}
+ ${pay.status === 'pending' ? ` +
+ Open + + QR +
` : ''} + ${pay.txHash ? `
Tx: ${pay.txHash.slice(0, 10)}...${pay.txHash.slice(-6)}
` : ''} +
+ `).join("")} +
`; + } + + private async createPaymentRequest() { + const desc = (this.shadow.querySelector('[data-field="pay-desc"]') as HTMLInputElement)?.value; + const amount = (this.shadow.querySelector('[data-field="pay-amount"]') as HTMLInputElement)?.value; + const token = (this.shadow.querySelector('[data-field="pay-token"]') as HTMLSelectElement)?.value || 'USDC'; + const recipient = (this.shadow.querySelector('[data-field="pay-recipient"]') as HTMLInputElement)?.value; + + if (!desc || !amount || !recipient) return; + + this.creatingPayment = true; + this.render(); + + try { + await fetch(`${this.getApiBase()}/api/payments`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + description: desc, + amount, + token, + recipientAddress: recipient, + chainId: 8453, + }), + }); + await this.loadData(); + } catch (e) { + console.error("Failed to create payment request:", e); + } + this.creatingPayment = false; + } + // ── Styles ── private getStyles(): string { @@ -716,7 +840,7 @@ class FolkCartShop extends HTMLElement { .input:focus { outline: none; border-color: var(--rs-primary); } .input-sm { max-width: 160px; } - .new-cart-form, .contribute-form { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.5rem; flex-wrap: wrap; } + .new-cart-form, .contribute-form, .new-payment-form { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.5rem; flex-wrap: wrap; } .url-input-row { display: flex; gap: 0.5rem; margin-bottom: 1rem; } diff --git a/modules/rcart/components/folk-payment-page.ts b/modules/rcart/components/folk-payment-page.ts new file mode 100644 index 0000000..e7d96f5 --- /dev/null +++ b/modules/rcart/components/folk-payment-page.ts @@ -0,0 +1,672 @@ +/** + * — Public payment page for QR code payment requests. + * + * Three-tab layout: + * 1. Card — Email → Transak iframe for fiat-to-crypto + * 2. Wallet — EIP-6963 wallet discovery → ERC-20 transfer + * 3. EncryptID — Passkey auth → derive EOA → sign tx + * + * Polls GET /api/payments/:id for status updates. + */ + +class FolkPaymentPage extends HTMLElement { + private shadow: ShadowRoot; + private space = 'default'; + private paymentId = ''; + private payment: any = null; + private loading = true; + private error = ''; + private activeTab: 'card' | 'wallet' | 'encryptid' = 'card'; + private pollTimer: ReturnType | null = null; + + // Card tab state + private cardEmail = ''; + private cardLoading = false; + private transakUrl = ''; + + // Wallet tab state + private walletProviders: any[] = []; + private walletDiscovery: any = null; + private walletConnected = false; + private walletAccount = ''; + private walletSending = false; + private walletTxHash = ''; + private walletError = ''; + private selectedProviderUuid = ''; + + // EncryptID tab state + private eidSigning = false; + private eidTxHash = ''; + private eidError = ''; + + // Editable amount (for amountEditable payments) + private customAmount = ''; + + // QR state + private qrDataUrl = ''; + + constructor() { + super(); + this.shadow = this.attachShadow({ mode: 'open' }); + } + + connectedCallback() { + this.space = this.getAttribute('space') || 'default'; + this.paymentId = this.getAttribute('payment-id') || ''; + this.loadPayment(); + this.startPolling(); + this.discoverWallets(); + } + + disconnectedCallback() { + this.stopPolling(); + this.walletDiscovery?.stop?.(); + } + + private getApiBase(): string { + const path = window.location.pathname; + const match = path.match(/^(\/[^/]+)?\/rcart/); + return match ? match[0] : '/rcart'; + } + + private async loadPayment() { + this.loading = true; + this.render(); + try { + const res = await fetch(`${this.getApiBase()}/api/payments/${this.paymentId}`); + if (!res.ok) throw new Error('Payment not found'); + this.payment = await res.json(); + this.generateQR(); + } catch (e) { + this.error = e instanceof Error ? e.message : 'Failed to load payment'; + } + this.loading = false; + this.render(); + } + + private startPolling() { + this.pollTimer = setInterval(async () => { + if (!this.paymentId) return; + try { + const res = await fetch(`${this.getApiBase()}/api/payments/${this.paymentId}`); + if (res.ok) { + const updated = await res.json(); + if (updated.status !== this.payment?.status) { + this.payment = updated; + this.render(); + } + } + } catch { /* ignore poll errors */ } + }, 5000); + } + + private stopPolling() { + if (this.pollTimer) { + clearInterval(this.pollTimer); + this.pollTimer = null; + } + } + + private async generateQR() { + try { + const QRCode = await import('qrcode'); + const payUrl = `${window.location.origin}/${this.space}/rcart/pay/${this.paymentId}`; + this.qrDataUrl = await QRCode.toDataURL(payUrl, { margin: 2, width: 200 }); + } catch { /* QR generation optional */ } + } + + // ── Wallet discovery (EIP-6963) ── + + private async discoverWallets() { + try { + const { WalletProviderDiscovery } = await import('../../../src/encryptid/eip6963'); + this.walletDiscovery = new WalletProviderDiscovery(); + this.walletDiscovery.onProvidersChanged((providers: any[]) => { + this.walletProviders = providers; + this.render(); + }); + this.walletDiscovery.start(); + } catch { /* no wallet support */ } + } + + // ── Card tab: Transak ── + + private async startTransak() { + if (!this.cardEmail) return; + this.cardLoading = true; + this.render(); + + try { + const res = await fetch(`${this.getApiBase()}/api/payments/${this.paymentId}/transak-session`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email: this.cardEmail }), + }); + const data = await res.json(); + if (!res.ok) throw new Error(data.error || 'Failed to create session'); + this.transakUrl = data.widgetUrl; + + // Listen for Transak postMessage events + window.addEventListener('message', this.handleTransakMessage); + } catch (e) { + this.error = e instanceof Error ? e.message : String(e); + } + this.cardLoading = false; + this.render(); + } + + private handleTransakMessage = (e: MessageEvent) => { + if (!e.data?.event_id) return; + if (e.data.event_id === 'TRANSAK_ORDER_SUCCESSFUL' || e.data.event_id === 'TRANSAK_ORDER_COMPLETED') { + const orderId = e.data.data?.id || e.data.data?.orderId; + this.updatePaymentStatus('paid', 'transak', null, orderId); + window.removeEventListener('message', this.handleTransakMessage); + } + }; + + // ── Wallet tab: EIP-6963 ── + + private async connectWallet(uuid: string) { + const provider = this.walletDiscovery?.getProvider(uuid); + if (!provider) return; + + this.selectedProviderUuid = uuid; + this.walletError = ''; + + try { + const { ExternalSigner } = await import('../../../src/encryptid/external-signer'); + const signer = new ExternalSigner(provider.provider); + + // Switch to correct chain + await signer.switchChain(this.payment.chainId); + + const accounts = await signer.getAccounts(); + if (accounts.length === 0) throw new Error('No accounts'); + + this.walletAccount = accounts[0]; + this.walletConnected = true; + } catch (e) { + this.walletError = e instanceof Error ? e.message : String(e); + } + this.render(); + } + + private async sendWalletPayment() { + if (!this.walletConnected || !this.walletAccount) return; + + const provider = this.walletDiscovery?.getProvider(this.selectedProviderUuid); + if (!provider) return; + + this.walletSending = true; + this.walletError = ''; + this.render(); + + try { + const { ExternalSigner } = await import('../../../src/encryptid/external-signer'); + const signer = new ExternalSigner(provider.provider); + + const p = this.payment; + const effectiveAmount = this.getEffectiveAmount(); + if (!effectiveAmount || effectiveAmount === '0') throw new Error('Enter an amount'); + let txHash: string; + + if (p.token === 'ETH') { + // Native ETH transfer + const weiAmount = BigInt(Math.round(parseFloat(effectiveAmount) * 1e18)); + txHash = await signer.sendTransaction({ + from: this.walletAccount, + to: p.recipientAddress, + value: '0x' + weiAmount.toString(16), + chainId: String(p.chainId), + }); + } else { + // ERC-20 transfer (USDC: 6 decimals) + const usdcAddress = p.usdcAddress; + if (!usdcAddress) throw new Error('USDC not supported on this chain'); + + const decimals = p.token === 'USDC' ? 6 : 18; + const rawAmount = BigInt(Math.round(parseFloat(effectiveAmount) * (10 ** decimals))); + + // transfer(address to, uint256 amount) — selector: 0xa9059cbb + const recipient = p.recipientAddress.slice(2).toLowerCase().padStart(64, '0'); + const amountHex = rawAmount.toString(16).padStart(64, '0'); + const data = `0xa9059cbb${recipient}${amountHex}`; + + txHash = await signer.sendTransaction({ + from: this.walletAccount, + to: usdcAddress, + value: '0x0', + data, + chainId: String(p.chainId), + }); + } + + this.walletTxHash = txHash; + await this.updatePaymentStatus('paid', 'wallet', txHash); + } catch (e) { + this.walletError = e instanceof Error ? e.message : String(e); + } + this.walletSending = false; + this.render(); + } + + // ── EncryptID tab: Passkey-derived EOA ── + + private async payWithEncryptID() { + this.eidSigning = true; + this.eidError = ''; + this.render(); + + try { + // 1. Authenticate with passkey + PRF + const { authenticatePasskey } = await import('../../../src/encryptid/webauthn'); + const { deriveEOAFromPRF } = await import('../../../src/encryptid/eoa-derivation'); + + const authResult = await authenticatePasskey(); + if (!authResult.prfOutput) throw new Error('Passkey PRF not supported — try a different browser or device'); + + const eoa = deriveEOAFromPRF(new Uint8Array(authResult.prfOutput)); + + // 2. Sign transaction with viem + const { privateKeyToAccount } = await import('viem/accounts'); + const { createWalletClient, http } = await import('viem'); + const { base, baseSepolia, mainnet } = await import('viem/chains'); + + const chainMap: Record = { + 8453: base, + 84532: baseSepolia, + 1: mainnet, + }; + + const chain = chainMap[this.payment.chainId]; + if (!chain) throw new Error(`Unsupported chain: ${this.payment.chainId}`); + + const hexKey = ('0x' + Array.from(eoa.privateKey).map(b => b.toString(16).padStart(2, '0')).join('')) as `0x${string}`; + const account = privateKeyToAccount(hexKey); + + const client = createWalletClient({ + account, + chain, + transport: http(), + }); + + const p = this.payment; + const effectiveAmount = this.getEffectiveAmount(); + if (!effectiveAmount || effectiveAmount === '0') throw new Error('Enter an amount'); + let txHash: `0x${string}`; + + if (p.token === 'ETH') { + txHash = await client.sendTransaction({ + account, + to: p.recipientAddress as `0x${string}`, + value: BigInt(Math.round(parseFloat(effectiveAmount) * 1e18)), + chain, + }); + } else { + // ERC-20 transfer + const usdcAddress = p.usdcAddress; + if (!usdcAddress) throw new Error('USDC not supported on this chain'); + + const decimals = p.token === 'USDC' ? 6 : 18; + const rawAmount = BigInt(Math.round(parseFloat(effectiveAmount) * (10 ** decimals))); + + const recipient = p.recipientAddress.slice(2).toLowerCase().padStart(64, '0'); + const amountHex = rawAmount.toString(16).padStart(64, '0'); + const data = `0xa9059cbb${recipient}${amountHex}` as `0x${string}`; + + txHash = await client.sendTransaction({ + account, + to: usdcAddress as `0x${string}`, + value: 0n, + data, + chain, + }); + } + + // Zero the private key + eoa.privateKey.fill(0); + + this.eidTxHash = txHash; + await this.updatePaymentStatus('paid', 'encryptid', txHash); + } catch (e) { + this.eidError = e instanceof Error ? e.message : String(e); + } + this.eidSigning = false; + this.render(); + } + + /** Get the effective payment amount — custom amount for editable payments, or the preset amount. */ + private getEffectiveAmount(): string { + const p = this.payment; + if (p.amountEditable && this.customAmount) return this.customAmount; + if (p.amount && p.amount !== '0') return p.amount; + return this.customAmount || '0'; + } + + // ── Status update ── + + private async updatePaymentStatus(status: string, method: string, txHash?: string | null, transakOrderId?: string | null) { + try { + await fetch(`${this.getApiBase()}/api/payments/${this.paymentId}/status`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + status, + paymentMethod: method, + txHash: txHash || undefined, + transakOrderId: transakOrderId || undefined, + }), + }); + await this.loadPayment(); + } catch { /* will be picked up by polling */ } + } + + // ── Render ── + + private render() { + this.shadow.innerHTML = ` + +
+ ${this.loading ? '
Loading payment...
' : + this.error && !this.payment ? `
${this.esc(this.error)}
` : + this.payment ? this.renderPayment() : '
Payment not found
'} +
`; + this.bindEvents(); + } + + private renderPayment(): string { + const p = this.payment; + const isPaid = p.status === 'paid' || p.status === 'confirmed'; + const isExpired = p.status === 'expired'; + const isCancelled = p.status === 'cancelled'; + const isTerminal = isPaid || isExpired || isCancelled; + + const chainNames: Record = { 8453: 'Base', 84532: 'Base Sepolia', 1: 'Ethereum' }; + const chainName = chainNames[p.chainId] || `Chain ${p.chainId}`; + + const showAmountInput = p.amountEditable && p.status === 'pending'; + const displayAmount = (!p.amount || p.amount === '0') && p.amountEditable ? 'Any amount' : `${p.amount} ${p.token}`; + + return ` +
+

Payment Request

+
${p.status}
+
+ +
+ ${showAmountInput ? ` +
+ + ${this.esc(p.token)} +
+ on ${chainName} + ` : ` + ${displayAmount} + ${p.fiatAmount ? `\u2248 $${this.esc(p.fiatAmount)} ${this.esc(p.fiatCurrency)}` : ''} + on ${chainName} + `} +
+ +
${this.esc(p.description)}
+ + ${isPaid ? this.renderPaidConfirmation() : + isTerminal ? `
${isExpired ? 'This payment request has expired.' : 'This payment request has been cancelled.'}
` : + this.renderPaymentTabs()} + + `; + } + + private renderPaidConfirmation(): string { + const p = this.payment; + const explorerBase: Record = { + 8453: 'https://basescan.org/tx/', + 84532: 'https://sepolia.basescan.org/tx/', + 1: 'https://etherscan.io/tx/', + }; + const explorer = explorerBase[p.chainId] || ''; + + return ` +
+
+

Payment Complete

+
+ ${p.paymentMethod ? `
Method: ${p.paymentMethod}
` : ''} + ${p.txHash ? `` : ''} + ${p.paid_at ? `
Paid: ${new Date(p.paid_at).toLocaleString()}
` : ''} +
+
`; + } + + private renderPaymentTabs(): string { + return ` +
+ + + +
+ +
+ ${this.activeTab === 'card' ? this.renderCardTab() : + this.activeTab === 'wallet' ? this.renderWalletTab() : + this.renderEncryptIDTab()} +
`; + } + + private renderCardTab(): string { + if (this.transakUrl) { + return ` +
+ +
`; + } + + return ` +
+

Pay with credit or debit card via Transak.

+
+ +
+ + ${this.error ? `
${this.esc(this.error)}
` : ''} +
`; + } + + private renderWalletTab(): string { + if (this.walletTxHash) { + return ` +
+
Transaction sent!
+
Tx: ${this.walletTxHash.slice(0, 14)}...${this.walletTxHash.slice(-10)}
+
`; + } + + if (this.walletConnected) { + return ` +
+

Connected: ${this.walletAccount.slice(0, 6)}...${this.walletAccount.slice(-4)}

+ + ${this.walletError ? `
${this.esc(this.walletError)}
` : ''} +
`; + } + + if (this.walletProviders.length === 0) { + return ` +
+

No wallets detected. Install MetaMask or another EIP-6963 compatible wallet.

+
`; + } + + return ` +
+

Select a wallet to connect:

+
+ ${this.walletProviders.map((p: any) => ` + + `).join('')} +
+ ${this.walletError ? `
${this.esc(this.walletError)}
` : ''} +
`; + } + + private renderEncryptIDTab(): string { + if (this.eidTxHash) { + return ` +
+
Transaction sent!
+
Tx: ${this.eidTxHash.slice(0, 14)}...${this.eidTxHash.slice(-10)}
+
`; + } + + return ` +
+

Pay using your EncryptID passkey. Your signing key is derived locally from your passkey and never leaves your device.

+ + ${this.eidError ? `
${this.esc(this.eidError)}
` : ''} +
`; + } + + private bindEvents() { + // Tab switching + this.shadow.querySelectorAll('[data-tab]').forEach((el) => { + el.addEventListener('click', () => { + this.activeTab = (el as HTMLElement).dataset.tab as any; + this.render(); + }); + }); + + // Custom amount for editable payments + const customAmtInput = this.shadow.querySelector('[data-field="custom-amount"]') as HTMLInputElement; + customAmtInput?.addEventListener('input', () => { this.customAmount = customAmtInput.value; }); + + // Card tab + const emailInput = this.shadow.querySelector('[data-field="card-email"]') as HTMLInputElement; + emailInput?.addEventListener('input', () => { this.cardEmail = emailInput.value; }); + this.shadow.querySelector('[data-action="start-transak"]')?.addEventListener('click', () => this.startTransak()); + + // Wallet tab + this.shadow.querySelectorAll('[data-wallet-uuid]').forEach((el) => { + el.addEventListener('click', () => this.connectWallet((el as HTMLElement).dataset.walletUuid!)); + }); + this.shadow.querySelector('[data-action="send-wallet"]')?.addEventListener('click', () => this.sendWalletPayment()); + + // EncryptID tab + this.shadow.querySelector('[data-action="pay-encryptid"]')?.addEventListener('click', () => this.payWithEncryptID()); + + // Copy URL + this.shadow.querySelector('[data-action="copy-url"]')?.addEventListener('click', () => { + navigator.clipboard.writeText(window.location.href); + const btn = this.shadow.querySelector('[data-action="copy-url"]') as HTMLElement; + if (btn) { btn.textContent = 'Copied!'; setTimeout(() => { btn.textContent = 'Copy'; }, 2000); } + }); + } + + private getStyles(): string { + return ` + :host { display: block; padding: 1.5rem; max-width: 560px; margin: 0 auto; } + * { box-sizing: border-box; } + + .payment-page { } + + .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; } + .title { color: var(--rs-text-primary); font-size: 1.25rem; font-weight: 700; margin: 0; } + + .status-badge { padding: 0.25rem 0.75rem; border-radius: 999px; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; } + .status-pending { background: rgba(251,191,36,0.15); color: #fbbf24; } + .status-paid, .status-confirmed { background: rgba(34,197,94,0.15); color: #4ade80; } + .status-expired { background: rgba(239,68,68,0.15); color: #f87171; } + .status-cancelled { background: rgba(156,163,175,0.15); color: #9ca3af; } + + .amount-display { text-align: center; margin-bottom: 1rem; } + .amount { display: block; font-size: 2rem; font-weight: 700; color: var(--rs-text-primary); } + .fiat-amount { display: block; font-size: 0.875rem; color: var(--rs-text-secondary); margin-top: 0.25rem; } + .chain-info { display: block; font-size: 0.75rem; color: var(--rs-text-muted); margin-top: 0.25rem; } + + .editable-amount { display: flex; align-items: center; justify-content: center; gap: 0.5rem; } + .amount-input { width: 160px; padding: 0.5rem 0.75rem; border-radius: 8px; border: 1px solid var(--rs-input-border); background: var(--rs-input-bg); color: var(--rs-text-primary); font-size: 1.75rem; font-weight: 700; text-align: center; } + .amount-input:focus { outline: none; border-color: var(--rs-primary); } + .amount-input::placeholder { color: var(--rs-text-muted); font-weight: 400; font-size: 1rem; } + .amount-token { color: var(--rs-text-secondary); font-size: 1.25rem; font-weight: 600; } + + .description { text-align: center; color: var(--rs-text-secondary); font-size: 0.9375rem; margin-bottom: 1.5rem; padding: 0.75rem; background: var(--rs-bg-surface); border-radius: 8px; border: 1px solid var(--rs-border); } + + .tabs { display: flex; gap: 0; border-bottom: 1px solid var(--rs-border); margin-bottom: 1.5rem; } + .tab { flex: 1; padding: 0.75rem 1rem; border: none; background: none; color: var(--rs-text-secondary); cursor: pointer; font-size: 0.875rem; font-weight: 500; border-bottom: 2px solid transparent; transition: all 0.15s; } + .tab:hover { color: var(--rs-text-primary); } + .tab.active { color: var(--rs-primary-hover); border-bottom-color: var(--rs-primary); } + + .tab-content { min-height: 180px; } + .tab-body { } + .tab-desc { color: var(--rs-text-secondary); font-size: 0.875rem; margin: 0 0 1rem; line-height: 1.5; } + + .form-row { margin-bottom: 1rem; } + + .input { width: 100%; padding: 0.625rem 0.75rem; border-radius: 8px; border: 1px solid var(--rs-input-border); background: var(--rs-input-bg); color: var(--rs-input-text); font-size: 0.875rem; } + .input:focus { outline: none; border-color: var(--rs-primary); } + + .btn { padding: 0.625rem 1.25rem; border-radius: 8px; border: 1px solid var(--rs-border); background: var(--rs-bg-surface); color: var(--rs-text-primary); cursor: pointer; font-size: 0.875rem; font-weight: 500; } + .btn:hover { border-color: var(--rs-border-strong); } + .btn-primary { background: var(--rs-primary-hover); border-color: var(--rs-primary); color: #fff; width: 100%; } + .btn-primary:hover { background: #4338ca; } + .btn-primary:disabled { opacity: 0.5; cursor: not-allowed; } + .btn-sm { padding: 0.375rem 0.75rem; font-size: 0.8125rem; } + + .wallet-list { display: flex; flex-direction: column; gap: 0.5rem; } + .wallet-btn { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 1rem; border-radius: 8px; border: 1px solid var(--rs-border); background: var(--rs-bg-surface); color: var(--rs-text-primary); cursor: pointer; font-size: 0.875rem; transition: border-color 0.15s; } + .wallet-btn:hover { border-color: var(--rs-primary); } + .wallet-icon { width: 28px; height: 28px; border-radius: 6px; } + + .field-error { color: #f87171; font-size: 0.8125rem; margin-top: 0.75rem; } + .success-msg { color: #4ade80; font-size: 1rem; font-weight: 600; text-align: center; margin-bottom: 0.5rem; } + .tx-hash { color: var(--rs-text-secondary); font-size: 0.8125rem; text-align: center; font-family: monospace; } + + .confirmation { text-align: center; padding: 2rem 1rem; } + .confirm-icon { font-size: 3rem; color: #4ade80; margin-bottom: 0.5rem; } + .confirmation h2 { color: var(--rs-text-primary); font-size: 1.25rem; margin: 0 0 1rem; } + .confirm-details { color: var(--rs-text-secondary); font-size: 0.875rem; line-height: 1.8; } + .confirm-details a { color: var(--rs-primary-hover); text-decoration: none; } + .confirm-details a:hover { text-decoration: underline; } + + .terminal-msg { text-align: center; padding: 2rem; color: var(--rs-text-muted); font-size: 0.875rem; } + + .transak-container { border-radius: 8px; overflow: hidden; border: 1px solid var(--rs-border); } + .transak-iframe { width: 100%; height: 600px; border: none; } + + .footer { margin-top: 2rem; border-top: 1px solid var(--rs-border); padding-top: 1.5rem; } + .qr-section { display: flex; flex-direction: column; align-items: center; gap: 1rem; } + .qr-code { border-radius: 8px; background: #fff; padding: 8px; } + .share-url { display: flex; gap: 0.5rem; width: 100%; } + .share-input { flex: 1; padding: 0.5rem 0.75rem; border-radius: 8px; border: 1px solid var(--rs-input-border); background: var(--rs-input-bg); color: var(--rs-input-text); font-size: 0.75rem; font-family: monospace; } + + .loading { text-align: center; padding: 3rem; color: var(--rs-text-secondary); } + .error { text-align: center; padding: 3rem; color: #f87171; } + `; + } + + private esc(s: string): string { + const d = document.createElement('div'); + d.textContent = s; + return d.innerHTML; + } +} + +customElements.define('folk-payment-page', FolkPaymentPage); diff --git a/modules/rcart/components/folk-payment-request.ts b/modules/rcart/components/folk-payment-request.ts new file mode 100644 index 0000000..87f1fba --- /dev/null +++ b/modules/rcart/components/folk-payment-request.ts @@ -0,0 +1,455 @@ +/** + * — Self-service payment request generator. + * + * User flow: + * 1. Authenticate with EncryptID passkey → derives wallet address + * 2. Fill in description, amount (or leave editable), token, chain + * 3. Click "Generate QR" → creates payment request via API + * 4. Shows QR code + shareable link, ready to print/share + */ + +class FolkPaymentRequest extends HTMLElement { + private shadow: ShadowRoot; + private space = 'default'; + + // Auth state + private authenticated = false; + private walletAddress = ''; + private did = ''; + private authError = ''; + private authenticating = false; + + // Form state + private description = ''; + private amount = ''; + private amountEditable = false; + private token: 'USDC' | 'ETH' = 'USDC'; + private chainId = 8453; + + // Result state + private generating = false; + private generatedPayment: any = null; + private qrDataUrl = ''; + private payUrl = ''; + private qrSvgUrl = ''; + + private static readonly CHAIN_OPTIONS = [ + { id: 8453, name: 'Base' }, + { id: 84532, name: 'Base Sepolia (testnet)' }, + { id: 1, name: 'Ethereum' }, + ]; + + constructor() { + super(); + this.shadow = this.attachShadow({ mode: 'open' }); + } + + connectedCallback() { + this.space = this.getAttribute('space') || 'default'; + this.checkExistingSession(); + this.render(); + } + + private getApiBase(): string { + const path = window.location.pathname; + const match = path.match(/^(\/[^/]+)?\/rcart/); + return match ? match[0] : '/rcart'; + } + + // ── Auth ── + + private async checkExistingSession() { + try { + const { getSessionManager } = await import('../../../src/encryptid/session'); + const session = getSessionManager(); + if (session.isValid()) { + this.did = session.getDID() || ''; + const state = session.getSession(); + this.walletAddress = state?.claims?.eid?.walletAddress || ''; + + // If session exists but no wallet address, try deriving from key manager + if (!this.walletAddress) { + try { + const { getKeyManager } = await import('../../../src/encryptid/key-derivation'); + const km = getKeyManager(); + if (km.isInitialized()) { + const keys = await km.getKeys(); + if (keys.eoaAddress) this.walletAddress = keys.eoaAddress; + } + } catch { /* key manager not ready */ } + } + + if (this.walletAddress) { + this.authenticated = true; + this.render(); + } + } + } catch { /* session module not available */ } + } + + private async authenticate() { + this.authenticating = true; + this.authError = ''; + this.render(); + + try { + const { authenticatePasskey } = await import('../../../src/encryptid/webauthn'); + const { deriveEOAFromPRF } = await import('../../../src/encryptid/eoa-derivation'); + const { getSessionManager } = await import('../../../src/encryptid/session'); + const { EncryptIDKeyManager } = await import('../../../src/encryptid/key-derivation'); + + const result = await authenticatePasskey(); + if (!result.prfOutput) { + throw new Error('Your passkey does not support PRF — wallet address cannot be derived'); + } + + const eoa = deriveEOAFromPRF(new Uint8Array(result.prfOutput)); + this.walletAddress = eoa.address; + + // Initialize key manager for session + const km = new EncryptIDKeyManager(); + await km.initFromPRF(result.prfOutput); + const keys = await km.getKeys(); + this.did = keys.did; + + // Create session + const session = getSessionManager(); + await session.createSession(result, keys.did, { + encrypt: true, + sign: true, + wallet: true, + }); + + // Zero private key — we don't need to sign anything here + eoa.privateKey.fill(0); + + this.authenticated = true; + } catch (e) { + this.authError = e instanceof Error ? e.message : String(e); + } + this.authenticating = false; + this.render(); + } + + // ── Generate payment request ── + + private async generatePayment() { + if (!this.walletAddress || !this.description) return; + if (!this.amountEditable && !this.amount) return; + + this.generating = true; + this.render(); + + try { + const { getSessionManager } = await import('../../../src/encryptid/session'); + const session = getSessionManager(); + const accessToken = session.getSession()?.accessToken; + + const res = await fetch(`${this.getApiBase()}/api/payments`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...(accessToken ? { 'Authorization': `Bearer ${accessToken}` } : {}), + }, + body: JSON.stringify({ + description: this.description, + amount: this.amount || '0', + amountEditable: this.amountEditable, + token: this.token, + chainId: this.chainId, + recipientAddress: this.walletAddress, + }), + }); + + if (!res.ok) { + const err = await res.json(); + throw new Error(err.error || 'Failed to create payment request'); + } + + this.generatedPayment = await res.json(); + + // Build URLs + const host = window.location.origin; + this.payUrl = `${host}/${this.space}/rcart/pay/${this.generatedPayment.id}`; + this.qrSvgUrl = `${host}/${this.space}/rcart/api/payments/${this.generatedPayment.id}/qr`; + + // Generate client-side QR + try { + const QRCode = await import('qrcode'); + this.qrDataUrl = await QRCode.toDataURL(this.payUrl, { + margin: 2, + width: 280, + color: { dark: '#1e1b4b', light: '#ffffff' }, + }); + } catch { /* QR generation optional */ } + } catch (e) { + this.authError = e instanceof Error ? e.message : String(e); + } + this.generating = false; + this.render(); + } + + private reset() { + this.generatedPayment = null; + this.qrDataUrl = ''; + this.payUrl = ''; + this.qrSvgUrl = ''; + this.description = ''; + this.amount = ''; + this.amountEditable = false; + this.render(); + } + + // ── Render ── + + private render() { + this.shadow.innerHTML = ` + +
+

Request Payment

+

Generate a QR code anyone can scan to pay you

+ + ${this.generatedPayment ? this.renderResult() : + !this.authenticated ? this.renderAuthStep() : + this.renderForm()} +
`; + this.bindEvents(); + } + + private renderAuthStep(): string { + return ` +
+
1
+
+

Connect your identity

+

Authenticate with your EncryptID passkey to derive your wallet address. Your private key never leaves your device.

+ + ${this.authError ? `
${this.esc(this.authError)}
` : ''} +
+
`; + } + + private renderForm(): string { + return ` +
+ Receiving wallet + ${this.walletAddress.slice(0, 6)}...${this.walletAddress.slice(-4)} + ${this.walletAddress} +
+ +
+
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+ + +
+ + + ${this.authError ? `
${this.esc(this.authError)}
` : ''} +
`; + } + + private renderResult(): string { + const p = this.generatedPayment; + const amountDisplay = this.amountEditable && (!p.amount || p.amount === '0') + ? 'Any amount' + : `${p.amount} ${p.token}`; + + return ` +
+
+
${this.esc(p.description)}
+
${amountDisplay}
+ ${this.amountEditable ? '
Amount editable by payer
' : ''} +
+ +
+ ${this.qrDataUrl + ? `Payment QR Code` + : `Payment QR Code`} +
+ + + + +
`; + } + + private bindEvents() { + // Auth + this.shadow.querySelector('[data-action="authenticate"]')?.addEventListener('click', () => this.authenticate()); + + // Form inputs + const descInput = this.shadow.querySelector('[data-field="description"]') as HTMLInputElement; + descInput?.addEventListener('input', () => { this.description = descInput.value; }); + + const amtInput = this.shadow.querySelector('[data-field="amount"]') as HTMLInputElement; + amtInput?.addEventListener('input', () => { this.amount = amtInput.value; }); + + const tokenSelect = this.shadow.querySelector('[data-field="token"]') as HTMLSelectElement; + tokenSelect?.addEventListener('change', () => { this.token = tokenSelect.value as 'USDC' | 'ETH'; }); + + const chainSelect = this.shadow.querySelector('[data-field="chainId"]') as HTMLSelectElement; + chainSelect?.addEventListener('change', () => { this.chainId = parseInt(chainSelect.value); }); + + const editableCheck = this.shadow.querySelector('[data-field="amountEditable"]') as HTMLInputElement; + editableCheck?.addEventListener('change', () => { + this.amountEditable = editableCheck.checked; + this.render(); + }); + + // Generate + this.shadow.querySelector('[data-action="generate"]')?.addEventListener('click', () => this.generatePayment()); + + // Result actions + this.shadow.querySelector('[data-action="copy-url"]')?.addEventListener('click', () => { + navigator.clipboard.writeText(this.payUrl); + const btn = this.shadow.querySelector('[data-action="copy-url"]') as HTMLElement; + if (btn) { btn.textContent = 'Copied!'; setTimeout(() => { btn.textContent = 'Copy'; }, 2000); } + }); + + this.shadow.querySelector('[data-action="print"]')?.addEventListener('click', () => { + const printWin = window.open('', '_blank', 'width=400,height=500'); + if (printWin) { + printWin.document.write(` + Payment QR + + +
${this.esc(this.description)}
+
${this.amountEditable && (!this.amount || this.amount === '0') ? 'Any amount' : `${this.amount || this.generatedPayment?.amount} ${this.token}`}
+ ${this.amountEditable ? '
Amount editable by payer
' : ''} + QR +
${this.payUrl}
+ `); + printWin.document.close(); + printWin.focus(); + printWin.print(); + } + }); + + this.shadow.querySelector('[data-action="new-request"]')?.addEventListener('click', () => this.reset()); + } + + private getStyles(): string { + return ` + :host { display: block; padding: 1.5rem; max-width: 520px; margin: 0 auto; } + * { box-sizing: border-box; } + + .page-title { color: var(--rs-text-primary); font-size: 1.5rem; font-weight: 700; margin: 0 0 0.25rem; text-align: center; } + .page-subtitle { color: var(--rs-text-secondary); font-size: 0.9375rem; text-align: center; margin: 0 0 2rem; } + + .step-card { display: flex; gap: 1rem; padding: 1.5rem; background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 12px; } + .step-num { width: 32px; height: 32px; border-radius: 50%; background: var(--rs-primary-hover); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.875rem; flex-shrink: 0; } + .step-content { flex: 1; } + .step-title { color: var(--rs-text-primary); font-size: 1.125rem; font-weight: 600; margin: 0 0 0.5rem; } + .step-desc { color: var(--rs-text-secondary); font-size: 0.875rem; line-height: 1.5; margin: 0 0 1rem; } + + .wallet-badge { background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 10px; padding: 0.875rem 1rem; margin-bottom: 1.5rem; display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; } + .wallet-label { color: var(--rs-text-secondary); font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; } + .wallet-addr { color: var(--rs-text-primary); font-family: monospace; font-size: 0.9375rem; font-weight: 600; } + .wallet-full { display: none; } + + .form { display: flex; flex-direction: column; gap: 1rem; } + .field { display: flex; flex-direction: column; gap: 0.375rem; } + .field-row { display: flex; gap: 0.75rem; } + .label { color: var(--rs-text-secondary); font-size: 0.8125rem; font-weight: 500; } + .required { color: #f87171; } + .hint { color: var(--rs-text-muted); font-weight: 400; } + + .input { padding: 0.625rem 0.75rem; border-radius: 8px; border: 1px solid var(--rs-input-border); background: var(--rs-input-bg); color: var(--rs-input-text); font-size: 0.875rem; } + .input:focus { outline: none; border-color: var(--rs-primary); } + select.input { cursor: pointer; } + + .field-check { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0; } + .field-check input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--rs-primary-hover); cursor: pointer; } + .field-check label { color: var(--rs-text-primary); font-size: 0.875rem; cursor: pointer; } + + .btn { padding: 0.625rem 1.25rem; border-radius: 8px; border: 1px solid var(--rs-border); background: var(--rs-bg-surface); color: var(--rs-text-primary); cursor: pointer; font-size: 0.875rem; font-weight: 500; text-decoration: none; text-align: center; display: inline-block; } + .btn:hover { border-color: var(--rs-border-strong); } + .btn-primary { background: var(--rs-primary-hover); border-color: var(--rs-primary); color: #fff; width: 100%; } + .btn-primary:hover { background: #4338ca; } + .btn-primary:disabled { opacity: 0.5; cursor: not-allowed; } + .btn-lg { padding: 0.875rem 1.5rem; font-size: 1rem; margin-top: 0.5rem; } + .btn-sm { padding: 0.375rem 0.75rem; font-size: 0.8125rem; } + .btn-outline { background: transparent; border: 1px solid var(--rs-border); color: var(--rs-text-secondary); width: 100%; } + .btn-outline:hover { border-color: var(--rs-text-secondary); color: var(--rs-text-primary); } + + .field-error { color: #f87171; font-size: 0.8125rem; margin-top: 0.5rem; } + + /* Result */ + .result { text-align: center; } + .result-header { margin-bottom: 1.5rem; } + .result-desc { color: var(--rs-text-secondary); font-size: 1rem; margin-bottom: 0.25rem; } + .result-amount { color: var(--rs-text-primary); font-size: 2rem; font-weight: 700; } + .result-hint { color: var(--rs-text-muted); font-size: 0.8125rem; margin-top: 0.25rem; } + + .qr-display { margin: 0 auto 1.5rem; padding: 1rem; background: #fff; border-radius: 12px; display: inline-block; } + .qr-img { display: block; max-width: 280px; border-radius: 4px; } + + .share-section { } + .share-row { display: flex; gap: 0.5rem; margin-bottom: 0.75rem; } + .share-input { flex: 1; padding: 0.5rem 0.75rem; border-radius: 8px; border: 1px solid var(--rs-input-border); background: var(--rs-input-bg); color: var(--rs-input-text); font-size: 0.75rem; font-family: monospace; } + .action-row { display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; } + + @media (max-width: 480px) { + .field-row { flex-direction: column; } + .action-row { flex-direction: column; } + } + `; + } + + private esc(s: string): string { + const d = document.createElement('div'); + d.textContent = s; + return d.innerHTML; + } +} + +customElements.define('folk-payment-request', FolkPaymentRequest); diff --git a/modules/rcart/mod.ts b/modules/rcart/mod.ts index a1a3a39..0e1bd55 100644 --- a/modules/rcart/mod.ts +++ b/modules/rcart/mod.ts @@ -19,13 +19,18 @@ import { renderLanding } from "./landing"; import type { SyncServer } from '../../server/local-first/sync-server'; import { catalogSchema, orderSchema, shoppingCartSchema, shoppingCartIndexSchema, + paymentRequestSchema, catalogDocId, orderDocId, shoppingCartDocId, shoppingCartIndexDocId, + paymentRequestDocId, type CatalogDoc, type CatalogEntry, type OrderDoc, type OrderMeta, type ShoppingCartDoc, type ShoppingCartIndexDoc, + type PaymentRequestDoc, type PaymentRequestMeta, type CartItem, type CartStatus, } from './schemas'; import { extractProductFromUrl } from './extract'; +import { createTransakWidgetUrl } from '../../shared/transak'; +import QRCode from 'qrcode'; let _syncServer: SyncServer | null = null; @@ -1093,6 +1098,304 @@ routes.get("/api/cart/summary", async (c) => { }); }); +// ── PAYMENT REQUEST helpers ── + +/** Get all payment request docs for a space. */ +function getSpacePaymentDocs(space: string): Array<{ docId: string; doc: Automerge.Doc }> { + const prefix = `${space}:cart:payments:`; + const results: Array<{ docId: string; doc: Automerge.Doc }> = []; + for (const id of _syncServer!.listDocs()) { + if (id.startsWith(prefix)) { + const doc = _syncServer!.getDoc(id); + if (doc) results.push({ docId: id, doc }); + } + } + return results; +} + +// USDC contract addresses +const USDC_ADDRESSES: Record = { + 8453: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // Base + 84532: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Base Sepolia + 1: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // Ethereum +}; + +// ── PAYMENT REQUEST ROUTES ── + +// POST /api/payments — Create payment request (auth required) +routes.post("/api/payments", async (c) => { + const space = c.req.param("space") || "demo"; + const token = extractToken(c.req.raw.headers); + if (!token) return c.json({ error: "Authentication required" }, 401); + + let claims; + try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); } + + const body = await c.req.json(); + const { + description, amount, amountEditable = false, + token: payToken = 'USDC', + chainId = 8453, recipientAddress, + fiatAmount = null, fiatCurrency = 'USD', + expiresIn = 0, // seconds, 0 = no expiry + } = body; + + if (!description || !recipientAddress) { + return c.json({ error: "Required: description, recipientAddress" }, 400); + } + if (!amountEditable && !amount) { + return c.json({ error: "Required: amount (or set amountEditable: true)" }, 400); + } + + const paymentId = crypto.randomUUID(); + const now = Date.now(); + const expiresAt = expiresIn > 0 ? now + expiresIn * 1000 : 0; + + const docId = paymentRequestDocId(space, paymentId); + const payDoc = Automerge.change(Automerge.init(), 'create payment request', (d) => { + const init = paymentRequestSchema.init(); + Object.assign(d, init); + d.meta.spaceSlug = space; + d.payment.id = paymentId; + d.payment.description = description; + d.payment.amount = amount ? String(amount) : '0'; + d.payment.amountEditable = !!amountEditable; + d.payment.token = payToken; + d.payment.chainId = chainId; + d.payment.recipientAddress = recipientAddress; + d.payment.fiatAmount = fiatAmount ? String(fiatAmount) : null; + d.payment.fiatCurrency = fiatCurrency; + d.payment.creatorDid = claims.sub; + d.payment.status = 'pending'; + d.payment.createdAt = now; + d.payment.updatedAt = now; + d.payment.expiresAt = expiresAt; + }); + _syncServer!.setDoc(docId, payDoc); + + const host = c.req.header("host") || "rspace.online"; + const payUrl = `https://${host}/${space}/rcart/pay/${paymentId}`; + + return c.json({ + id: paymentId, + description, + amount: String(amount), + token: payToken, + chainId, + recipientAddress, + status: 'pending', + payUrl, + qrUrl: `https://${host}/${space}/rcart/api/payments/${paymentId}/qr`, + created_at: new Date(now).toISOString(), + }, 201); +}); + +// GET /api/payments — List my payment requests (auth required) +routes.get("/api/payments", async (c) => { + const space = c.req.param("space") || "demo"; + const token = extractToken(c.req.raw.headers); + if (!token) return c.json({ error: "Authentication required" }, 401); + + let claims; + try { claims = await verifyEncryptIDToken(token); } catch { return c.json({ error: "Invalid token" }, 401); } + + const paymentDocs = getSpacePaymentDocs(space); + const payments = paymentDocs + .map(({ doc }) => doc.payment) + .filter((p) => p.creatorDid === claims.sub) + .sort((a, b) => b.createdAt - a.createdAt) + .map((p) => ({ + id: p.id, + description: p.description, + amount: p.amount, + token: p.token, + chainId: p.chainId, + recipientAddress: p.recipientAddress, + fiatAmount: p.fiatAmount, + fiatCurrency: p.fiatCurrency, + status: p.status, + paymentMethod: p.paymentMethod, + txHash: p.txHash, + created_at: new Date(p.createdAt).toISOString(), + paid_at: p.paidAt ? new Date(p.paidAt).toISOString() : null, + })); + + return c.json({ payments }); +}); + +// GET /api/payments/:id — Get payment details (public) +routes.get("/api/payments/:id", async (c) => { + const space = c.req.param("space") || "demo"; + const paymentId = c.req.param("id"); + const docId = paymentRequestDocId(space, paymentId); + const doc = _syncServer!.getDoc(docId); + if (!doc) return c.json({ error: "Payment request not found" }, 404); + + const p = doc.payment; + + // Check expiry + if (p.expiresAt > 0 && Date.now() > p.expiresAt && p.status === 'pending') { + _syncServer!.changeDoc(docId, 'expire payment', (d) => { + d.payment.status = 'expired'; + d.payment.updatedAt = Date.now(); + }); + return c.json({ + ...paymentToResponse(p), + status: 'expired', + usdcAddress: USDC_ADDRESSES[p.chainId] || null, + }); + } + + return c.json({ + ...paymentToResponse(p), + usdcAddress: USDC_ADDRESSES[p.chainId] || null, + }); +}); + +// PATCH /api/payments/:id/status — Update payment status +routes.patch("/api/payments/:id/status", async (c) => { + const space = c.req.param("space") || "demo"; + const paymentId = c.req.param("id"); + const docId = paymentRequestDocId(space, paymentId); + const doc = _syncServer!.getDoc(docId); + if (!doc) return c.json({ error: "Payment request not found" }, 404); + + const body = await c.req.json(); + const { status, txHash, paymentMethod, payerIdentity, transakOrderId, amount } = body; + const validStatuses = ['pending', 'paid', 'confirmed', 'expired', 'cancelled']; + if (status && !validStatuses.includes(status)) { + return c.json({ error: `status must be one of: ${validStatuses.join(", ")}` }, 400); + } + + const now = Date.now(); + _syncServer!.changeDoc(docId, `payment status → ${status || 'update'}`, (d) => { + if (status) d.payment.status = status; + if (txHash) d.payment.txHash = txHash; + if (paymentMethod) d.payment.paymentMethod = paymentMethod; + if (payerIdentity) d.payment.payerIdentity = payerIdentity; + if (transakOrderId) d.payment.transakOrderId = transakOrderId; + // Allow amount update only if payment is editable and still pending + if (amount && d.payment.amountEditable && d.payment.status === 'pending') { + d.payment.amount = String(amount); + } + d.payment.updatedAt = now; + if (status === 'paid') d.payment.paidAt = now; + }); + + const updated = _syncServer!.getDoc(docId); + return c.json(paymentToResponse(updated!.payment)); +}); + +// GET /api/payments/:id/qr — QR code SVG +routes.get("/api/payments/:id/qr", async (c) => { + const space = c.req.param("space") || "demo"; + const paymentId = c.req.param("id"); + const docId = paymentRequestDocId(space, paymentId); + const doc = _syncServer!.getDoc(docId); + if (!doc) return c.json({ error: "Payment request not found" }, 404); + + const host = c.req.header("host") || "rspace.online"; + const payUrl = `https://${host}/${space}/rcart/pay/${paymentId}`; + + const svg = await QRCode.toString(payUrl, { type: 'svg', margin: 2 }); + return c.body(svg, 200, { 'Content-Type': 'image/svg+xml', 'Cache-Control': 'public, max-age=3600' }); +}); + +// POST /api/payments/:id/transak-session — Get Transak widget URL (public) +routes.post("/api/payments/:id/transak-session", async (c) => { + const space = c.req.param("space") || "demo"; + const paymentId = c.req.param("id"); + const docId = paymentRequestDocId(space, paymentId); + const doc = _syncServer!.getDoc(docId); + if (!doc) return c.json({ error: "Payment request not found" }, 404); + + const p = doc.payment; + if (p.status !== 'pending') return c.json({ error: "Payment is no longer pending" }, 400); + + const { email } = await c.req.json(); + if (!email) return c.json({ error: "Required: email" }, 400); + + const transakApiKey = process.env.TRANSAK_API_KEY; + if (!transakApiKey) return c.json({ error: "Transak not configured" }, 503); + + const networkMap: Record = { 8453: 'base', 84532: 'base', 1: 'ethereum' }; + + try { + const widgetUrl = await createTransakWidgetUrl({ + apiKey: transakApiKey, + referrerDomain: 'rspace.online', + cryptoCurrencyCode: p.token, + network: networkMap[p.chainId] || 'base', + defaultCryptoCurrency: p.token, + walletAddress: p.recipientAddress, + disableWalletAddressForm: 'true', + cryptoAmount: p.amount, + partnerOrderId: `pay-${paymentId}`, + email, + themeColor: '6366f1', + hideMenu: 'true', + }); + + return c.json({ widgetUrl }); + } catch (err) { + return c.json({ error: err instanceof Error ? err.message : String(err) }, 500); + } +}); + +function paymentToResponse(p: PaymentRequestMeta) { + return { + id: p.id, + description: p.description, + amount: p.amount, + amountEditable: p.amountEditable, + token: p.token, + chainId: p.chainId, + recipientAddress: p.recipientAddress, + fiatAmount: p.fiatAmount, + fiatCurrency: p.fiatCurrency, + status: p.status, + paymentMethod: p.paymentMethod, + txHash: p.txHash, + payerIdentity: p.payerIdentity, + transakOrderId: p.transakOrderId, + created_at: new Date(p.createdAt).toISOString(), + updated_at: new Date(p.updatedAt).toISOString(), + paid_at: p.paidAt ? new Date(p.paidAt).toISOString() : null, + expires_at: p.expiresAt ? new Date(p.expiresAt).toISOString() : null, + }; +} + +// ── Page route: request payment (self-service QR generator) ── +routes.get("/request", (c) => { + const space = c.req.param("space") || "demo"; + return c.html(renderShell({ + title: `Request Payment | rCart`, + moduleId: "rcart", + spaceSlug: space, + modules: getModuleInfoList(), + theme: "dark", + body: ``, + scripts: ``, + styles: ``, + })); +}); + +// ── Page route: payment page ── +routes.get("/pay/:id", (c) => { + const space = c.req.param("space") || "demo"; + const paymentId = c.req.param("id"); + return c.html(renderShell({ + title: `Payment | rCart`, + moduleId: "rcart", + spaceSlug: space, + modules: getModuleInfoList(), + theme: "dark", + body: ``, + scripts: ``, + styles: ``, + })); +}); + // ── Page route: shop ── routes.get("/", (c) => { const space = c.req.param("space") || "demo"; @@ -1164,6 +1467,7 @@ export const cartModule: RSpaceModule = { { pattern: '{space}:cart:orders:{orderId}', description: 'Order document', init: orderSchema.init }, { pattern: '{space}:cart:shopping:{cartId}', description: 'Shopping cart', init: shoppingCartSchema.init }, { pattern: '{space}:cart:shopping-index', description: 'Shopping cart index', init: shoppingCartIndexSchema.init }, + { pattern: '{space}:cart:payments:{paymentId}', description: 'Payment request', init: paymentRequestSchema.init }, ], routes, standaloneDomain: "rcart.online", diff --git a/modules/rcart/schemas.ts b/modules/rcart/schemas.ts index 01b11c2..1cb65f3 100644 --- a/modules/rcart/schemas.ts +++ b/modules/rcart/schemas.ts @@ -274,6 +274,77 @@ export const shoppingCartIndexSchema: DocSchema = { }), }; +// ── Payment Request types ── + +export interface PaymentRequestMeta { + id: string; + description: string; + amount: string; + amountEditable: boolean; + token: string; + chainId: number; + recipientAddress: string; + fiatAmount: string | null; + fiatCurrency: string; + creatorDid: string; + status: 'pending' | 'paid' | 'confirmed' | 'expired' | 'cancelled'; + paymentMethod: 'transak' | 'wallet' | 'encryptid' | null; + txHash: string | null; + payerIdentity: string | null; + transakOrderId: string | null; + createdAt: number; + updatedAt: number; + paidAt: number; + expiresAt: number; +} + +export interface PaymentRequestDoc { + meta: { + module: string; + collection: string; + version: number; + spaceSlug: string; + createdAt: number; + }; + payment: PaymentRequestMeta; +} + +export const paymentRequestSchema: DocSchema = { + module: 'cart', + collection: 'payments', + version: 1, + init: (): PaymentRequestDoc => ({ + meta: { + module: 'cart', + collection: 'payments', + version: 1, + spaceSlug: '', + createdAt: Date.now(), + }, + payment: { + id: '', + description: '', + amount: '0', + amountEditable: false, + token: 'USDC', + chainId: 8453, + recipientAddress: '', + fiatAmount: null, + fiatCurrency: 'USD', + creatorDid: '', + status: 'pending', + paymentMethod: null, + txHash: null, + payerIdentity: null, + transakOrderId: null, + createdAt: Date.now(), + updatedAt: Date.now(), + paidAt: 0, + expiresAt: 0, + }, + }), +}; + // ── Helpers ── export function catalogDocId(space: string) { @@ -291,3 +362,7 @@ export function shoppingCartDocId(space: string, cartId: string) { export function shoppingCartIndexDocId(space: string) { return `${space}:cart:shopping-index` as const; } + +export function paymentRequestDocId(space: string, paymentId: string) { + return `${space}:cart:payments:${paymentId}` as const; +} diff --git a/modules/rnetwork/landing.ts b/modules/rnetwork/landing.ts index d47c026..09a548e 100644 --- a/modules/rnetwork/landing.ts +++ b/modules/rnetwork/landing.ts @@ -19,6 +19,11 @@ export function renderLanding(): string { Explore Network Create a Space +

+ + Start Guided Tour → + +

diff --git a/package-lock.json b/package-lock.json index 51412c9..35d95ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,24 +11,52 @@ "@automerge/automerge": "^2.2.8", "@aws-sdk/client-s3": "^3.700.0", "@encryptid/sdk": "file:../encryptid-sdk", + "@google/genai": "^1.43.0", + "@google/generative-ai": "^0.24.1", "@lit/reactive-element": "^2.0.4", + "@noble/curves": "^1.8.0", + "@noble/hashes": "^1.7.0", + "@openfort/openfort-node": "^0.7.0", + "@tiptap/core": "^3.20.0", + "@tiptap/extension-code-block-lowlight": "^3.20.0", + "@tiptap/extension-image": "^3.20.0", + "@tiptap/extension-link": "^3.20.0", + "@tiptap/extension-placeholder": "^3.20.0", + "@tiptap/extension-task-item": "^3.20.0", + "@tiptap/extension-task-list": "^3.20.0", + "@tiptap/extension-typography": "^3.20.0", + "@tiptap/extension-underline": "^3.20.0", + "@tiptap/pm": "^3.20.0", + "@tiptap/starter-kit": "^3.20.0", + "@types/qrcode": "^1.5.6", "@x402/core": "^2.3.1", - "@x402/evm": "^2.3.1", + "@x402/evm": "^2.5.0", + "cron-parser": "^5.5.0", "hono": "^4.11.7", "imapflow": "^1.0.170", + "jose": "^6.0.11", + "jszip": "^3.10.1", + "lowlight": "^3.3.0", "mailparser": "^3.7.2", + "marked": "^17.0.3", "nodemailer": "^6.9.0", "perfect-arrows": "^0.3.7", "perfect-freehand": "^1.2.2", "postgres": "^3.4.5", - "sharp": "^0.33.0" + "qrcode": "^1.5.4", + "sharp": "^0.33.0", + "web-push": "^3.6.7", + "yaml": "^2.8.2" }, "devDependencies": { "@types/mailparser": "^3.4.0", "@types/node": "^22.10.1", "@types/nodemailer": "^6.4.0", + "@types/web-push": "^3.6.4", + "@x402/fetch": "^2.5.0", "bun-types": "^1.1.38", "typescript": "^5.7.2", + "viem": "^2.46.3", "vite": "^6.0.3", "vite-plugin-top-level-await": "^1.6.0", "vite-plugin-wasm": "^3.5.0" @@ -36,7 +64,7 @@ }, "../encryptid-sdk": { "name": "@encryptid/sdk", - "version": "0.1.0", + "version": "0.2.0", "license": "MIT", "dependencies": { "@noble/curves": "^2.0.1", @@ -1478,6 +1506,38 @@ "node": ">=18" } }, + "node_modules/@google/genai": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.44.0.tgz", + "integrity": "sha512-kRt9ZtuXmz+tLlcNntN/VV4LRdpl6ZOu5B1KbfNgfR65db15O6sUQcwnwLka8sT/V6qysD93fWrgJHF2L7dA9A==", + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@google/generative-ai": { + "version": "0.24.1", + "resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.24.1.tgz", + "integrity": "sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", @@ -1839,6 +1899,23 @@ "url": "https://opencollective.com/libvips" } }, + "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/@lit-labs/ssr-dom-shim": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.1.tgz", @@ -1867,36 +1944,154 @@ } }, "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", "license": "MIT", - "peer": true, "dependencies": { - "@noble/hashes": "1.3.2" + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", "license": "MIT", "engines": { - "node": ">= 16" + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, + "node_modules/@openfort/openfort-node": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@openfort/openfort-node/-/openfort-node-0.7.7.tgz", + "integrity": "sha512-z/8tFDJwj9G18Vjr3Fki2wwgZLhnbjhB7FHhPUBmonKjv9V7nGa5bwVWRnX/Q4THIN7xmRhrJIFf9K2bpRyQTQ==", + "license": "MIT", + "dependencies": { + "@openfort/shield-js": "^0.1.33", + "@types/node": "*", + "@types/node-fetch": "^2.5.7", + "axios": "^1.7.0", + "axios-retry": "^4.5.0", + "bs58": "^6.0.0", + "jose": "^5.2.0", + "node-fetch": "^2.6.0", + "viem": "^2.21.0" + } + }, + "node_modules/@openfort/openfort-node/node_modules/jose": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz", + "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/@openfort/shield-js": { + "version": "0.1.35", + "resolved": "https://registry.npmjs.org/@openfort/shield-js/-/shield-js-0.1.35.tgz", + "integrity": "sha512-S/v73xRnbgv5i47IRJ7cPWOnJ1bUTOJN+048Y8mJ+ya+iRJUXKTTqePaWApvfrVHHcKA+li8QGyDsRRDefLLVQ==", + "license": "MIT", + "dependencies": { + "axios": "1.13.6", + "axios-retry": "4.5.0" + } + }, "node_modules/@pinojs/redact": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", "license": "MIT" }, + "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/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@remirror/core-constants": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", + "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", + "license": "MIT" + }, "node_modules/@rollup/plugin-virtual": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz", @@ -2288,33 +2483,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", - "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.8.0" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@scure/bip39": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", @@ -2328,18 +2496,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip39/node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", @@ -3361,6 +3517,461 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/@tiptap/core": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.20.1.tgz", + "integrity": "sha512-SwkPEWIfaDEZjC8SEIi4kZjqIYUbRgLUHUuQezo5GbphUNC8kM1pi3C3EtoOPtxXrEbY6e4pWEzW54Pcrd+rVA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/pm": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-blockquote": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.20.1.tgz", + "integrity": "sha512-WzNXk/63PQI2fav4Ta6P0GmYRyu8Gap1pV3VUqaVK829iJ6Zt1T21xayATHEHWMK27VT1GLPJkx9Ycr2jfDyQw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-bold": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.20.1.tgz", + "integrity": "sha512-fz++Qv6Rk/Hov0IYG/r7TJ1Y4zWkuGONe0UN5g0KY32NIMg3HeOHicbi4xsNWTm9uAOl3eawWDkezEMrleObMw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-bullet-list": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.20.1.tgz", + "integrity": "sha512-mbrlvOZo5OF3vLhp+3fk9KuL/6J/wsN0QxF6ZFRAHzQ9NkJdtdfARcBeBnkWXGN8inB6YxbTGY1/E4lmBkOpOw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-code": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.20.1.tgz", + "integrity": "sha512-509DHINIA/Gg+eTG7TEkfsS8RUiPLH5xZNyLRT0A1oaoaJmECKfrV6aAm05IdfTyqDqz6LW5pbnX6DdUC4keug==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-code-block": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.20.1.tgz", + "integrity": "sha512-vKejwBq+Nlj4Ybd3qOyDxIQKzYymdNH+8eXkKwGShk2nfLJIxq69DCyGvmuHgipIO1qcYPJ149UNpGN+YGcdmA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1", + "@tiptap/pm": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-code-block-lowlight": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-3.20.1.tgz", + "integrity": "sha512-QJXZGN43HArGNl5HeiPF1fXZZs6FWJwG3wTr9v+OwsM8EX3ixyblIoeY0/nmFBlQqci49ZA/KfCqVwfGNlRj5A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1", + "@tiptap/extension-code-block": "^3.20.1", + "@tiptap/pm": "^3.20.1", + "highlight.js": "^11", + "lowlight": "^2 || ^3" + } + }, + "node_modules/@tiptap/extension-document": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.20.1.tgz", + "integrity": "sha512-9vrqdGmRV7bQCSY3NLgu7UhIwgOCDp4sKqMNsoNRX0aZ021QQMTvBQDPkiRkCf7MNsnWrNNnr52PVnULEn3vFQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-dropcursor": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.20.1.tgz", + "integrity": "sha512-K18L9FX4znn+ViPSIbTLOGcIaXMx/gLNwAPE8wPLwswbHhQqdiY1zzdBw6drgOc1Hicvebo2dIoUlSXOZsOEcw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-gapcursor": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.20.1.tgz", + "integrity": "sha512-kZOtttV6Ai8VUAgEng3h4WKFbtdSNJ6ps7r0cRPY+FctWhVmgNb/JJwwyC+vSilR7nRENAhrA/Cv/RxVlvLw+g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-hard-break": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.20.1.tgz", + "integrity": "sha512-9sKpmg/IIdlLXimYWUZ3PplIRcehv4Oc7V1miTqlnAthMzjMqigDkjjgte4JZV67RdnDJTQkRw8TklCAU28Emg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-heading": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.20.1.tgz", + "integrity": "sha512-unudyfQP6FxnyWinxvPqe/51DG91J6AaJm666RnAubgYMCgym+33kBftx4j4A6qf+ddWYbD00thMNKOnVLjAEQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-horizontal-rule": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.20.1.tgz", + "integrity": "sha512-rjFKFXNntdl0jay8oIGFvvykHlpyQTLmrH3Ag2fj3i8yh6MVvqhtaDomYQbw5sxECd5hBkL+T4n2d2DRuVw/QQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1", + "@tiptap/pm": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-image": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-image/-/extension-image-3.20.1.tgz", + "integrity": "sha512-/GPFSLNdYSZQ0E6VBXSAk0UFtDdn98HT1Aa2tO+STELqc5jAdFB42dfFnTC6KQzTvcUOUYkE2S1Q22YC5H2XNQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-italic": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.20.1.tgz", + "integrity": "sha512-ZYRX13Kt8tR8JOzSXirH3pRpi8x30o7LHxZY58uXBdUvr3tFzOkh03qbN523+diidSVeHP/aMd/+IrplHRkQug==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-link": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.20.1.tgz", + "integrity": "sha512-oYTTIgsQMqpkSnJAuAc+UtIKMuI4lv9e1y4LfI1iYm6NkEUHhONppU59smhxHLzb3Ww7YpDffbp5IgDTAiJztA==", + "license": "MIT", + "dependencies": { + "linkifyjs": "^4.3.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1", + "@tiptap/pm": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-list": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.20.1.tgz", + "integrity": "sha512-euBRAn0mkV7R2VEE+AuOt3R0j9RHEMFXamPFmtvTo8IInxDClusrm6mJoDjS8gCGAXsQCRiAe1SCQBPgGbOOwg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1", + "@tiptap/pm": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-list-item": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.20.1.tgz", + "integrity": "sha512-tzgnyTW82lYJkUnadYbatwkI9dLz/OWRSWuFpQPRje/ItmFMWuQ9c9NDD8qLbXPdEYnvrgSAA+ipCD/1G0qA0Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-list-keymap": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.20.1.tgz", + "integrity": "sha512-Dr0xsQKx0XPOgDg7xqoWwfv7FFwZ3WeF3eOjqh3rDXlNHMj1v+UW5cj1HLphrsAZHTrVTn2C+VWPJkMZrSbpvQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-ordered-list": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.20.1.tgz", + "integrity": "sha512-Y+3Ad7OwAdagqdYwCnbqf7/to5ypD4NnUNHA0TXRCs7cAHRA8AdgPoIcGFpaaSpV86oosNU3yfeJouYeroffog==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-paragraph": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.20.1.tgz", + "integrity": "sha512-QFrAtXNyv7JSnomMQc1nx5AnG9mMznfbYJAbdOQYVdbLtAzTfiTuNPNbQrufy5ZGtGaHxDCoaygu2QEfzaKG+Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-placeholder": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-3.20.1.tgz", + "integrity": "sha512-k+jfbCugYGuIFBdojukgEopGazIMOgHrw46FnyN2X/6ICOIjQP2rh2ObslrsUOsJYoEevxCsNF9hZl1HvWX66g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.20.1.tgz", + "integrity": "sha512-EYgyma10lpsY+rwbVQL9u+gA7hBlKLSMFH7Zgd37FSxukOjr+HE8iKPQQ+SwbGejyDsPlLT8Z5Jnuxo5Ng90Pg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-task-item": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-task-item/-/extension-task-item-3.20.1.tgz", + "integrity": "sha512-ZdQld5Jzw/b/zl9TSA3KNkucmQhW5lHS/0YEKb+eFvxMwdHTKSpsTQzrfzbJixcdSqsuKJB+uUCwDDB+l0CRlA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-task-list": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-task-list/-/extension-task-list-3.20.1.tgz", + "integrity": "sha512-fbWsbp2ybWZUn9zcdgvFIcVya7v8kISuy91SULM1lhLwIsjNC15IPqp/ZEFJJJDKWBVr0o6bvLMsXwph/azO+w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-text": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.20.1.tgz", + "integrity": "sha512-7PlIbYW8UenV6NPOXHmv8IcmPGlGx6HFq66RmkJAOJRPXPkTLAiX0N8rQtzUJ6jDEHqoJpaHFEHJw0xzW1yF+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-typography": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-typography/-/extension-typography-3.20.1.tgz", + "integrity": "sha512-iqgB46r391vGlTr61jl6EWKGtyvorgIr+5Iqrze5ZSU8An2ZT0R4CPUI0FcLAAe0PuK8tCLhKtAidNXQotkOiw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extension-underline": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.20.1.tgz", + "integrity": "sha512-fmHvDKzwCgnZUwRreq8tYkb1YyEwgzZ6QQkAQ0CsCRtvRMqzerr3Duz0Als4i8voZTuGDEL3VR6nAJbLAb/wPg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1" + } + }, + "node_modules/@tiptap/extensions": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.20.1.tgz", + "integrity": "sha512-JRc/v+OBH0qLTdvQ7HvHWTxGJH73QOf1MC0R8NhOX2QnAbg2mPFv1h+FjGa2gfLGuCXBdWQomjekWkUKbC4e5A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.20.1", + "@tiptap/pm": "^3.20.1" + } + }, + "node_modules/@tiptap/pm": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.20.1.tgz", + "integrity": "sha512-6kCiGLvpES4AxcEuOhb7HR7/xIeJWMjZlb6J7e8zpiIh5BoQc7NoRdctsnmFEjZvC19bIasccshHQ7H2zchWqw==", + "license": "MIT", + "dependencies": { + "prosemirror-changeset": "^2.3.0", + "prosemirror-collab": "^1.3.1", + "prosemirror-commands": "^1.6.2", + "prosemirror-dropcursor": "^1.8.1", + "prosemirror-gapcursor": "^1.3.2", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", + "prosemirror-keymap": "^1.2.2", + "prosemirror-markdown": "^1.13.1", + "prosemirror-menu": "^1.2.4", + "prosemirror-model": "^1.24.1", + "prosemirror-schema-basic": "^1.2.3", + "prosemirror-schema-list": "^1.5.0", + "prosemirror-state": "^1.4.3", + "prosemirror-tables": "^1.6.4", + "prosemirror-trailing-node": "^3.0.0", + "prosemirror-transform": "^1.10.2", + "prosemirror-view": "^1.38.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/starter-kit": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.20.1.tgz", + "integrity": "sha512-opqWxL/4OTEiqmVC0wsU4o3JhAf6LycJ2G/gRIZVAIFLljI9uHfpPMTFGxZ5w9IVVJaP5PJysfwW/635kKqkrw==", + "license": "MIT", + "dependencies": { + "@tiptap/core": "^3.20.1", + "@tiptap/extension-blockquote": "^3.20.1", + "@tiptap/extension-bold": "^3.20.1", + "@tiptap/extension-bullet-list": "^3.20.1", + "@tiptap/extension-code": "^3.20.1", + "@tiptap/extension-code-block": "^3.20.1", + "@tiptap/extension-document": "^3.20.1", + "@tiptap/extension-dropcursor": "^3.20.1", + "@tiptap/extension-gapcursor": "^3.20.1", + "@tiptap/extension-hard-break": "^3.20.1", + "@tiptap/extension-heading": "^3.20.1", + "@tiptap/extension-horizontal-rule": "^3.20.1", + "@tiptap/extension-italic": "^3.20.1", + "@tiptap/extension-link": "^3.20.1", + "@tiptap/extension-list": "^3.20.1", + "@tiptap/extension-list-item": "^3.20.1", + "@tiptap/extension-list-keymap": "^3.20.1", + "@tiptap/extension-ordered-list": "^3.20.1", + "@tiptap/extension-paragraph": "^3.20.1", + "@tiptap/extension-strike": "^3.20.1", + "@tiptap/extension-text": "^3.20.1", + "@tiptap/extension-underline": "^3.20.1", + "@tiptap/extensions": "^3.20.1", + "@tiptap/pm": "^3.20.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -3368,6 +3979,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "license": "MIT" + }, "node_modules/@types/mailparser": { "version": "3.4.6", "resolved": "https://registry.npmjs.org/@types/mailparser/-/mailparser-3.4.6.tgz", @@ -3379,16 +4005,41 @@ "iconv-lite": "^0.6.3" } }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.19.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.11.tgz", "integrity": "sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.4" + } + }, "node_modules/@types/nodemailer": { "version": "6.4.23", "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.23.tgz", @@ -3399,35 +4050,66 @@ "@types/node": "*" } }, + "node_modules/@types/qrcode": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.6.tgz", + "integrity": "sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@types/web-push": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/@types/web-push/-/web-push-3.6.4.tgz", + "integrity": "sha512-GnJmSr40H3RAnj0s34FNTcJi1hmWFV5KXugE0mYWnYhgTAHLJ/dJKAwDmvPJYMke0RplY2XE9LnM4hqSqKIjhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@x402/core": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@x402/core/-/core-2.4.0.tgz", - "integrity": "sha512-g4K5dAVjevQftxCcpFlUDjO2AHE43FkO43VxwLCQ8ET3ki4aj2fzCcgvnXEj2eloJoocFS/Evt4pSTnP/4cFJw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@x402/core/-/core-2.6.0.tgz", + "integrity": "sha512-ISC/JeVss6xlKvor2rp18tJf9K5OQlIDDfZW1VZJQGDI2F4gy+HWxxkFfcQalCsPp4YUlwqh0YOkUxP+LTZWVg==", "license": "Apache-2.0", "dependencies": { "zod": "^3.24.2" } }, "node_modules/@x402/evm": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@x402/evm/-/evm-2.4.0.tgz", - "integrity": "sha512-k9qIEhJ5m8jZLPA44hcLEP9I1WC8nF375A7pX/3XGPA+H2UPUoY8fzBaQA2U+4lMv/eIyfz05klSj/8LzP1saA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@x402/evm/-/evm-2.6.0.tgz", + "integrity": "sha512-wPkNHf483gie1Up2sJSvERnW+VIEvMoT1KRXr09wSoSWgelglsJm+ug3gPPXKnT3C6AcmNAKZ12rBnu9Paff7g==", "license": "Apache-2.0", "dependencies": { - "@x402/core": "~2.4.0", - "@x402/extensions": "~2.4.0", + "@x402/core": "~2.6.0", + "@x402/extensions": "~2.6.0", "viem": "^2.39.3", "zod": "^3.24.2" } }, "node_modules/@x402/extensions": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@x402/extensions/-/extensions-2.4.0.tgz", - "integrity": "sha512-tg/mSAS+NgwUaOdjt8agSjVkO1s9NYy+kSPubVlZf/Fy884qu7dSW81Ixu1NRYEz+vBk0rtz6b+eEvS0v72tMQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@x402/extensions/-/extensions-2.6.0.tgz", + "integrity": "sha512-aLY9xAOOiRLKDN9HT2r9TYUXbD+IsoBces9qPZNVJGO2TBi2rfmbIBc3pcKCtWKn3iTvG2QFr3gpOFdpJRzqww==", "license": "Apache-2.0", "dependencies": { "@scure/base": "^1.2.6", - "@x402/core": "~2.4.0", + "@x402/core": "~2.6.0", "ajv": "^8.17.1", "siwe": "^2.3.2", "tweetnacl": "^1.0.3", @@ -3435,6 +4117,18 @@ "zod": "^3.24.2" } }, + "node_modules/@x402/fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@x402/fetch/-/fetch-2.6.0.tgz", + "integrity": "sha512-OnHXw/mv76ig4UBJEgfQIWHSWcrgIOT2i8RxEuGl12QtaYwSgBcgDub2GdllL/iIB9OneM1m0UWlrPh23JdVjQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@x402/core": "~2.6.0", + "viem": "^2.39.3", + "zod": "^3.24.2" + } + }, "node_modules/@zone-eu/mailsplit": { "version": "5.4.8", "resolved": "https://registry.npmjs.org/@zone-eu/mailsplit/-/mailsplit-5.4.8.tgz", @@ -3474,6 +4168,15 @@ "license": "MIT", "peer": true }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/ajv": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", @@ -3490,12 +4193,60 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "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/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/apg-js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/apg-js/-/apg-js-4.4.0.tgz", "integrity": "sha512-fefmXFknJmtgtNEXfPwZKYkMFX4Fyeyz+fNF6JWp87biGOPslJbCBVU158zvKRZfHBKnJDy8CMM40oLFGkXT8Q==", "license": "BSD-2-Clause" }, + "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/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "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/atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", @@ -3505,12 +4256,106 @@ "node": ">=8.0.0" } }, + "node_modules/axios": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", + "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios-retry": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", + "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", + "license": "Apache-2.0", + "dependencies": { + "is-retry-allowed": "^2.2.0" + }, + "peerDependencies": { + "axios": "0.x || 1.x" + } + }, + "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/base-x": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz", + "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==", + "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/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, "node_modules/bowser": { "version": "2.14.1", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", "license": "MIT" }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "license": "MIT", + "dependencies": { + "base-x": "^5.0.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, "node_modules/bun-types": { "version": "1.3.9", "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.3.9.tgz", @@ -3521,6 +4366,109 @@ "@types/node": "*" } }, + "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/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/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/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/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/cliui/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/cliui/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/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/cliui/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/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -3562,6 +4510,91 @@ "simple-swizzle": "^0.2.2" } }, + "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/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/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, + "node_modules/cron-parser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-5.5.0.tgz", + "integrity": "sha512-oML4lKUXxizYswqmxuOCpgFS8BNUJpIu6k/2HVHyaL8Ynnf3wdf9tkns0yRdJLSIjkJ+b0DXHMZEHGpMwjnPww==", + "license": "MIT", + "dependencies": { + "luxon": "^3.7.1" + }, + "engines": { + "node": ">=18" + } + }, + "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/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "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/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -3571,6 +4604,24 @@ "node": ">=0.10.0" } }, + "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/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -3580,6 +4631,25 @@ "node": ">=8" } }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -3635,6 +4705,41 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "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/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "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/encoding-japanese": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.2.0.tgz", @@ -3656,6 +4761,51 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "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.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "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/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", @@ -3698,6 +4848,18 @@ "@esbuild/win32-x64": "0.25.12" } }, + "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/ethers": { "version": "6.16.0", "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz", @@ -3727,6 +4889,32 @@ "node": ">=14.0.0" } }, + "node_modules/ethers/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ethers/node_modules/@types/node": { "version": "22.7.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", @@ -3751,12 +4939,40 @@ "license": "MIT", "peer": true }, + "node_modules/ethers/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "peer": true, + "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/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT" }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3815,6 +5031,106 @@ } } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "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/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "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/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3830,6 +5146,206 @@ "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/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gaxios/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "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/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/google-auth-library": { + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.1.tgz", + "integrity": "sha512-5awwuLrzNol+pFDmKJd0dKtZ0fPLAtoA5p7YO4ODsDu6ONJUVqbYwvv8y2ZBO5MBNp9TJXigB19710kYpBPdtA==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "7.1.3", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "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/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.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -3839,6 +5355,15 @@ "he": "bin/he" } }, + "node_modules/highlight.js": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/hono": { "version": "4.12.1", "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.1.tgz", @@ -3883,6 +5408,28 @@ "entities": "^4.4.0" } }, + "node_modules/http_ece": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http_ece/-/http_ece-1.2.0.tgz", + "integrity": "sha512-JrF8SSLVmcvc5NducxgyOrKXe3EsyHMgBFgSaIUGmArKe+rwr0uphRkRXvwiom3I+fpIfoItveHrfudL8/rxuA==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -3937,6 +5484,18 @@ "node": ">=6.0.0" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, + "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/ip-address": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", @@ -3952,6 +5511,39 @@ "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", "license": "MIT" }, + "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/is-retry-allowed": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", + "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/isows": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", @@ -3967,12 +5559,78 @@ "ws": "*" } }, + "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/jose": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.1.tgz", + "integrity": "sha512-jUaKr1yrbfaImV7R2TN/b3IcZzsw38/chqMpo2XJ7i2F8AfM/lA4G1goC3JVEwg0H7UldTmSt3P68nt31W7/mw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "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/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/leac": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", @@ -4006,6 +5664,15 @@ "integrity": "sha512-0Wd+GPz1O134cP62YU2GTOPNA7Qgl09XwCqM5zpBv87ERCXdfDtyKXvV7c9U22yWJh44QZqBocFnXN11K96qow==", "license": "MIT" }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", @@ -4015,6 +5682,60 @@ "uc.micro": "^2.0.0" } }, + "node_modules/linkifyjs": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.2.tgz", + "integrity": "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==", + "license": "MIT" + }, + "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/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lowlight": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-3.3.0.tgz", + "integrity": "sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.0.0", + "highlight.js": "~11.11.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "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/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/mailparser": { "version": "3.9.3", "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-3.9.3.tgz", @@ -4058,6 +5779,116 @@ "node": ">=6.0.0" } }, + "node_modules/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/marked": { + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.4.tgz", + "integrity": "sha512-NOmVMM+KAokHMvjWmC5N/ZOvgmSWuqJB8FoYI019j4ogb/PeRMKoKIjReZ2w3376kkA8dSJIP8uD993Kxc0iRQ==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "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/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, + "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/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "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/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/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/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -4077,6 +5908,46 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "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/nodemailer": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.1.tgz", @@ -4095,6 +5966,12 @@ "node": ">=14.0.0" } }, + "node_modules/orderedmap": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", + "license": "MIT" + }, "node_modules/ox": { "version": "0.12.4", "resolved": "https://registry.npmjs.org/ox/-/ox-0.12.4.tgz", @@ -4146,18 +6023,67 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/ox/node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "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": "^14.21.3 || >=16" + "node": ">=6" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, + "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/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "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/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, "node_modules/parseley": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", @@ -4171,6 +6097,40 @@ "url": "https://ko-fi.com/killymxi" } }, + "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-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-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/peberminta": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz", @@ -4252,6 +6212,15 @@ "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", "license": "MIT" }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -4294,6 +6263,12 @@ "url": "https://github.com/sponsors/porsager" } }, + "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/process-warning": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", @@ -4310,6 +6285,231 @@ ], "license": "MIT" }, + "node_modules/prosemirror-changeset": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.4.0.tgz", + "integrity": "sha512-LvqH2v7Q2SF6yxatuPP2e8vSUKS/L+xAU7dPDC4RMyHMhZoGDfBC74mYuyYF4gLqOEG758wajtyhNnsTkuhvng==", + "license": "MIT", + "dependencies": { + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-collab": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", + "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-commands": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", + "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.10.2" + } + }, + "node_modules/prosemirror-dropcursor": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", + "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "node_modules/prosemirror-gapcursor": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.1.tgz", + "integrity": "sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw==", + "license": "MIT", + "dependencies": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/prosemirror-history": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.0.tgz", + "integrity": "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.31.0", + "rope-sequence": "^1.3.0" + } + }, + "node_modules/prosemirror-inputrules": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.1.tgz", + "integrity": "sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-keymap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz", + "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "node_modules/prosemirror-markdown": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.4.tgz", + "integrity": "sha512-D98dm4cQ3Hs6EmjK500TdAOew4Z03EV71ajEFiWra3Upr7diytJsjF4mPV2dW+eK5uNectiRj0xFxYI9NLXDbw==", + "license": "MIT", + "dependencies": { + "@types/markdown-it": "^14.0.0", + "markdown-it": "^14.0.0", + "prosemirror-model": "^1.25.0" + } + }, + "node_modules/prosemirror-menu": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.3.0.tgz", + "integrity": "sha512-TImyPXCHPcDsSka2/lwJ6WjTASr4re/qWq1yoTTuLOqfXucwF6VcRa2LWCkM/EyTD1UO3CUwiH8qURJoWJRxwg==", + "license": "MIT", + "dependencies": { + "crelt": "^1.0.0", + "prosemirror-commands": "^1.0.0", + "prosemirror-history": "^1.0.0", + "prosemirror-state": "^1.0.0" + } + }, + "node_modules/prosemirror-model": { + "version": "1.25.4", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz", + "integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==", + "license": "MIT", + "dependencies": { + "orderedmap": "^2.0.0" + } + }, + "node_modules/prosemirror-schema-basic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz", + "integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.25.0" + } + }, + "node_modules/prosemirror-schema-list": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", + "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.7.3" + } + }, + "node_modules/prosemirror-state": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz", + "integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" + } + }, + "node_modules/prosemirror-tables": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.5.tgz", + "integrity": "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==", + "license": "MIT", + "dependencies": { + "prosemirror-keymap": "^1.2.3", + "prosemirror-model": "^1.25.4", + "prosemirror-state": "^1.4.4", + "prosemirror-transform": "^1.10.5", + "prosemirror-view": "^1.41.4" + } + }, + "node_modules/prosemirror-trailing-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz", + "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==", + "license": "MIT", + "dependencies": { + "@remirror/core-constants": "3.0.0", + "escape-string-regexp": "^4.0.0" + }, + "peerDependencies": { + "prosemirror-model": "^1.22.1", + "prosemirror-state": "^1.4.2", + "prosemirror-view": "^1.33.8" + } + }, + "node_modules/prosemirror-transform": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.11.0.tgz", + "integrity": "sha512-4I7Ce4KpygXb9bkiPS3hTEk4dSHorfRw8uI0pE8IhxlK2GXsqv5tIA7JUSxtSu7u8APVOTtbUBxTmnHIxVkIJw==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.21.0" + } + }, + "node_modules/prosemirror-view": { + "version": "1.41.6", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.6.tgz", + "integrity": "sha512-mxpcDG4hNQa/CPtzxjdlir5bJFDlm0/x5nGBbStB2BWX+XOQ9M8ekEG+ojqB5BcVu2Rc80/jssCMZzSstJuSYg==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.20.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4328,12 +6528,50 @@ "node": ">=6" } }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/quick-format-unescaped": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", "license": "MIT" }, + "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/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -4343,6 +6581,15 @@ "node": ">= 12.13.0" } }, + "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", @@ -4352,6 +6599,36 @@ "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/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "4.58.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.58.0.tgz", @@ -4397,6 +6674,32 @@ "fsevents": "~2.3.2" } }, + "node_modules/rope-sequence": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", + "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", + "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-stable-stringify": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", @@ -4436,6 +6739,18 @@ "node": ">=10" } }, + "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/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/sharp": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", @@ -4475,6 +6790,39 @@ "@img/sharp-win32-x64": "0.33.5" } }, + "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/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/simple-swizzle": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", @@ -4551,6 +6899,117 @@ "node": ">= 10.x" } }, + "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": "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/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/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/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/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/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/strnum": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.2.tgz", @@ -4601,6 +7060,12 @@ "tlds": "bin.js" } }, + "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/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -4637,7 +7102,6 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, "license": "MIT" }, "node_modules/uri-js": { @@ -4649,6 +7113,12 @@ "punycode": "^2.1.0" } }, + "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/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -4712,18 +7182,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/viem/node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/viem/node_modules/ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", @@ -4860,12 +7318,173 @@ "vite": "^2 || ^3 || ^4 || ^5 || ^6 || ^7" } }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, + "node_modules/web-push": { + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/web-push/-/web-push-3.6.7.tgz", + "integrity": "sha512-OpiIUe8cuGjrj3mMBFWY+e4MMIkW3SVT+7vEIjvD9kejGUypv8GPDf84JdPWskK8zMRIJ6xYGm+Kxr8YkPyA0A==", + "license": "MPL-2.0", + "dependencies": { + "asn1.js": "^5.3.0", + "http_ece": "1.2.0", + "https-proxy-agent": "^7.0.0", + "jws": "^4.0.0", + "minimist": "^1.2.5" + }, + "bin": { + "web-push": "src/cli.js" + }, + "engines": { + "node": ">= 16" + } + }, + "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-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/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-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/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/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/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/wrap-ansi-cjs/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/wrap-ansi-cjs/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/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/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -4882,6 +7501,103 @@ } } }, + "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/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "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/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/yargs/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/yargs/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/yargs/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/yargs/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/zod": { "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", diff --git a/package.json b/package.json index f81d6a8..0f4cec2 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@tiptap/extension-underline": "^3.20.0", "@tiptap/pm": "^3.20.0", "@tiptap/starter-kit": "^3.20.0", + "@types/qrcode": "^1.5.6", "@x402/core": "^2.3.1", "@x402/evm": "^2.5.0", "cron-parser": "^5.5.0", @@ -47,6 +48,7 @@ "perfect-arrows": "^0.3.7", "perfect-freehand": "^1.2.2", "postgres": "^3.4.5", + "qrcode": "^1.5.4", "sharp": "^0.33.0", "web-push": "^3.6.7", "yaml": "^2.8.2" diff --git a/shared/transak.ts b/shared/transak.ts new file mode 100644 index 0000000..4ed52a5 --- /dev/null +++ b/shared/transak.ts @@ -0,0 +1,87 @@ +/** + * Transak API utilities — shared across rFlows and rCart. + * + * Handles access token management (cached 6 days) and + * widget URL generation via Transak's session API. + */ + +let _transakAccessToken: string | null = null; +let _transakTokenExpiry = 0; + +export async function getTransakAccessToken(): Promise { + if (_transakAccessToken && Date.now() < _transakTokenExpiry) return _transakAccessToken; + + const apiKey = process.env.TRANSAK_API_KEY; + const apiSecret = process.env.TRANSAK_SECRET; + if (!apiKey || !apiSecret) throw new Error("Transak credentials not configured"); + + const env = process.env.TRANSAK_ENV || 'PRODUCTION'; + const baseUrl = env === 'PRODUCTION' + ? 'https://api.transak.com' + : 'https://api-stg.transak.com'; + + const res = await fetch(`${baseUrl}/partners/api/v2/refresh-token`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'api-secret': apiSecret, + }, + body: JSON.stringify({ apiKey }), + }); + + if (!res.ok) { + const text = await res.text(); + throw new Error(`Transak token refresh failed (${res.status}): ${text}`); + } + + const data = await res.json() as any; + _transakAccessToken = data.data?.accessToken || data.accessToken; + if (!_transakAccessToken) throw new Error("No accessToken in Transak response"); + + // Cache for 6 days (tokens valid for 7) + _transakTokenExpiry = Date.now() + 6 * 24 * 60 * 60 * 1000; + console.log('[transak] Access token refreshed'); + return _transakAccessToken; +} + +export async function createTransakWidgetUrl(params: Record): Promise { + const accessToken = await getTransakAccessToken(); + const env = process.env.TRANSAK_ENV || 'PRODUCTION'; + const gatewayUrl = env === 'PRODUCTION' + ? 'https://api-gateway.transak.com' + : 'https://api-gateway-stg.transak.com'; + + const res = await fetch(`${gatewayUrl}/api/v2/auth/session`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'access-token': accessToken, + }, + body: JSON.stringify({ widgetParams: params }), + }); + + if (!res.ok) { + const text = await res.text(); + // If token expired, clear cache and retry once + if (res.status === 401 || res.status === 403) { + _transakAccessToken = null; + _transakTokenExpiry = 0; + const retryToken = await getTransakAccessToken(); + const retry = await fetch(`${gatewayUrl}/api/v2/auth/session`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'access-token': retryToken, + }, + body: JSON.stringify({ widgetParams: params }), + }); + if (!retry.ok) throw new Error(`Transak widget URL failed on retry (${retry.status}): ${await retry.text()}`); + const retryData = await retry.json() as any; + return retryData.data?.widgetUrl; + } + throw new Error(`Transak widget URL failed (${res.status}): ${text}`); + } + + const data = await res.json() as any; + return data.data?.widgetUrl; +} diff --git a/vite.config.ts b/vite.config.ts index b676caf..be06997 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -156,6 +156,46 @@ export default defineConfig({ }, }); + // Build payment page component + await build({ + configFile: false, + root: resolve(__dirname, "modules/rcart/components"), + build: { + emptyOutDir: false, + outDir: resolve(__dirname, "dist/modules/rcart"), + lib: { + entry: resolve(__dirname, "modules/rcart/components/folk-payment-page.ts"), + formats: ["es"], + fileName: () => "folk-payment-page.js", + }, + rollupOptions: { + output: { + entryFileNames: "folk-payment-page.js", + }, + }, + }, + }); + + // Build payment request (QR generator) component + await build({ + configFile: false, + root: resolve(__dirname, "modules/rcart/components"), + build: { + emptyOutDir: false, + outDir: resolve(__dirname, "dist/modules/rcart"), + lib: { + entry: resolve(__dirname, "modules/rcart/components/folk-payment-request.ts"), + formats: ["es"], + fileName: () => "folk-payment-request.js", + }, + rollupOptions: { + output: { + entryFileNames: "folk-payment-request.js", + }, + }, + }, + }); + // Copy cart CSS mkdirSync(resolve(__dirname, "dist/modules/rcart"), { recursive: true }); copyFileSync(