@01.works/visual-review 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- import{r as e}from"./install-BXWJcrQ8.js";import{i as t,n,r,t as i}from"./reviewer-auth-presentation-CAm-YbaR.js";function a(e){let t=[`01works-reviewer-device-proof-v1`,e.purpose,e.deviceSessionId,e.challengeId,e.challenge,String(e.counter),String(e.expiresAt),e.invitationId,e.origin,e.pathname];return new TextEncoder().encode(t.map(e=>`${e.length}:${e}`).join(``))}const o=`reviewer-device-credentials-v1`;function s(){try{return globalThis.indexedDB?new u(globalThis.indexedDB):null}catch{return null}}async function c(e=globalThis.crypto){if(!e?.subtle||typeof e.randomUUID!=`function`)throw Error(`Visual Review device authentication requires Web Crypto`);let t=await e.subtle.generateKey({name:`ECDSA`,namedCurve:`P-256`},!1,[`sign`,`verify`]);if(!(t instanceof Object)||!(`privateKey`in t)||!(`publicKey`in t)||t.privateKey.extractable)throw Error(`Visual Review could not create a non-extractable device key`);let n=await e.subtle.exportKey(`jwk`,t.publicKey);if(n.kty!==`EC`||n.crv!==`P-256`||typeof n.x!=`string`||typeof n.y!=`string`)throw Error(`Visual Review received an invalid device public key`);return{deviceSessionId:e.randomUUID(),privateKey:t.privateKey,publicKey:{kty:`EC`,crv:`P-256`,x:n.x,y:n.y}}}async function l(e,t,n=globalThis.crypto){if(e.extractable||e.type!==`private`||e.algorithm.name!==`ECDSA`||!e.usages.includes(`sign`))throw Error(`Visual Review device key is invalid`);let r=await n.subtle.sign({name:`ECDSA`,hash:`SHA-256`},e,a(t));return m(new Uint8Array(r))}var u=class{factory;constructor(e){this.factory=e}async get(e){let t=await this.open();try{return d(await f(t.transaction(o,`readonly`).objectStore(o).get(e)))}finally{t.close()}}async set(e,t){let n=await this.open();try{await p(n.transaction(o,`readwrite`),n=>{n.put(t,e)})}finally{n.close()}}async delete(e){let t=await this.open();try{await p(t.transaction(o,`readwrite`),t=>{t.delete(e)})}finally{t.close()}}open(){return new Promise((e,t)=>{let n=this.factory.open(`01works-visual-review`,1);n.onupgradeneeded=()=>{n.result.objectStoreNames.contains(o)||n.result.createObjectStore(o)},n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error??Error(`IndexedDB open failed`)),n.onblocked=()=>t(Error(`IndexedDB upgrade blocked`))})}};function d(e){if(!e||typeof e!=`object`||Array.isArray(e))return null;let t=e;return typeof t.deviceSessionId!=`string`||!Number.isSafeInteger(t.expiresAt)||(t.expiresAt??0)<=Date.now()||t.invitationId!==void 0&&typeof t.invitationId!=`string`||!t.privateKey||t.privateKey.type!==`private`||t.privateKey.extractable||t.privateKey.algorithm.name!==`ECDSA`||!t.privateKey.usages.includes(`sign`)?null:t}function f(e){return new Promise((t,n)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>n(e.error??Error(`IndexedDB request failed`))})}function p(e,t){return new Promise((n,r)=>{e.oncomplete=()=>n(),e.onerror=()=>r(e.error??Error(`IndexedDB transaction failed`)),e.onabort=()=>r(e.error??Error(`IndexedDB transaction aborted`)),t(e.objectStore(o))})}function m(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replaceAll(`+`,`-`).replaceAll(`/`,`_`).replace(/=+$/u,``)}var h=class extends Error{code;status;constructor(e,t,n){super(t),this.code=e,this.status=n,this.name=`HostedBootstrapError`}};function g(e={}){return _(e)}function _(t={},n={}){let r=e(t.serviceUrl??`https://review.01.works`),i=globalThis.fetch,a=t.fetch??(typeof i==`function`?i.bind(globalThis):void 0),o=n.now??Date.now,c=new Map,l=n.reviewerDeviceStore===void 0?s():n.reviewerDeviceStore,u=n.crypto??globalThis.crypto,d=n.reviewerSessionStorage===void 0?U(W(),G()):U(n.reviewerSessionStorage);if(typeof a!=`function`)throw Error(`Visual Review bootstrap requires the Fetch API`);return{async resolve(e){let t=F(e),i=await L(r,a,t,e.signal),s=o(),f={serviceUrl:r,...n.instantAuthDatabaseFactory===void 0?{}:{databaseFactory:n.instantAuthDatabaseFactory},redeemEmailInvitation:async e=>(await D(r,a,e)).refreshToken,acceptInvitation:async e=>{let t=await a(`${r}/v1/invitations/accept`,{method:`POST`,headers:{accept:`application/json`,authorization:`Bearer ${e.refreshToken}`,"content-type":`application/json`},body:JSON.stringify({invitationId:e.invitationId,...e.displayName===void 0?{}:{displayName:e.displayName}}),cache:`no-store`,credentials:`omit`,signal:e.signal}),n=await Z(t);if(!t.ok)throw new h(Q(n,`error`)??`INVITATION_ACCEPT_FAILED`,Q(n,`message`)??`리뷰 초대 수락에 실패했습니다.`,t.status)},resolveReviewPage:e=>I(r,a,e)},p=i.apiVersion===2?await v({config:i,convexRuntimeFactory:n.convexRuntimeFactory??(await import(`./convex-runtime-DY-himGr.js`)).createConvexReviewRuntime,fetcher:a,memorySessions:c,navigateToAccountBridge:n.navigateToAccountBridge,reviewerDeviceStore:l,cryptoProvider:u,request:e,legacySessionStorages:d,serviceUrl:r}):{...await(n.instantRuntimeFactory??(await import(`./instant-runtime-UFycxLQ8.js`)).createInstantReviewRuntime)(i.instantAppId,f).resolve(e),sessionScope:`browser`,sessionExpiresAt:i.invitationExpiresAt},m=p.resolvePage;if(!m)return p;let g=async t=>{await L(r,a,{invitationId:e.invitationId,origin:t.location.origin,pathname:t.location.pathname},t.signal),s=o()};return{...p,resolvePage:async e=>(o()-s>=3e5&&await g(e),m(e))}}}}async function v(e){let t=e.config.accessScope?.kind===`project`?e.config.accessScope:null,n=H(e.serviceUrl,e.request.location.origin,t?.locator??e.config.sessionLocator??e.request.invitationId),r=H(e.serviceUrl,e.request.location.origin,e.request.invitationId);Y(e.legacySessionStorages,n),r!==n&&Y(e.legacySessionStorages,r);let a;if(t){if(a=await K(e.reviewerDeviceStore,e.memorySessions,n),a&&!a.invitationId&&(await J(e.reviewerDeviceStore,e.memorySessions,n),a=null),!a){let n=await c(e.cryptoProvider);a=e.request.accountToken?await ee(e,e.request.accountToken,n).catch(r=>{if(!(r instanceof h))throw r;if(r.code===`INVITATION_NOT_FOUND`&&t.mode===`email`)return y(e,t.locator,n);if(r.code===`INVITATION_TOKEN_USED`||r.code===`INVITATION_TOKEN_INVALID`||r.code===`ACCOUNT_ASSERTION_EXPIRED`||r.code===`AUTH_REQUIRED`||r.code===`INVALID_INPUT`)return x(e,t.locator);throw r}):e.request.accountBridgeAttempted?t.mode===`link`?await b(e,t.locator,n):await y(e,t.locator,n):await x(e,t.locator)}}else if(e.request.emailToken){await i(e.request.authHost,e.request.signal,e.request.styleNonce);let t=await c(e.cryptoProvider);try{a=await E(e.serviceUrl,e.fetcher,{invitationId:e.request.invitationId,emailToken:e.request.emailToken,origin:e.request.location.origin,pathname:e.request.location.pathname,signal:e.request.signal,device:t})}catch(n){if(!(n instanceof h)||n.code!==`INVITATION_TOKEN_USED`)throw n;a=await S(e,t)}}else a=await K(e.reviewerDeviceStore,e.memorySessions,n),!a&&r!==n&&(a=await K(e.reviewerDeviceStore,e.memorySessions,r),a&&await J(e.reviewerDeviceStore,e.memorySessions,r));a||=await S(e,await c(e.cryptoProvider));let o=t?a.invitationId:e.request.invitationId;if(!o)throw new h(`INVALID_PROJECT_ACCESS_RESPONSE`,`프로젝트 리뷰 인증 응답이 올바르지 않습니다.`,502);a={...a,invitationId:o},await q(e.reviewerDeviceStore,e.memorySessions,n,a);let{expiresAt:s}=a,l={...e.request,invitationId:o,emailToken:void 0,accountToken:void 0,accountBridgeAttempted:void 0};return{...await e.convexRuntimeFactory(e.config.convexUrl,{fetchAccessToken:t=>C(e.serviceUrl,e.fetcher,a,t,e.cryptoProvider,()=>J(e.reviewerDeviceStore,e.memorySessions,n))}).resolve(l),sessionScope:`browser`,sessionExpiresAt:s??e.config.invitationExpiresAt,clearLocalSession:()=>{J(e.reviewerDeviceStore,e.memorySessions,n);let t=new AbortController,r=setTimeout(()=>t.abort(),5e3);T(e.serviceUrl,e.fetcher,a,{invitationId:o,origin:e.request.location.origin,pathname:e.request.location.pathname,forceRefreshToken:!1,signal:t.signal},e.cryptoProvider).catch(()=>void 0).finally(()=>clearTimeout(r))}}}async function y(e,t,n){let i={reviewLocator:t,pathname:e.request.location.pathname,signal:e.request.signal};return r(e.request.authHost,e.request.signal,{requestCode:t=>k(e.serviceUrl,e.fetcher,{...i,email:t}),verifyCode:(t,r,a,o)=>A(e.serviceUrl,e.fetcher,{...i,challengeId:t,attemptId:r,email:a,code:o,device:n})},e.request.styleNonce)}async function b(e,t,r){let i=await n(e.request.authHost,e.request.signal,``,e.request.styleNonce),a=await e.fetcher(`${e.serviceUrl}/v1/reviewer/link/start`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify({reviewLocator:t,displayName:i,pathname:e.request.location.pathname,deviceSessionId:r.deviceSessionId,devicePublicKey:r.publicKey}),cache:`no-store`,credentials:`omit`,signal:e.request.signal}),o=await Z(a),s=Q(o,`invitationId`),c=Q(o,`deviceSessionId`),l=V($(o,`expiresAt`));if(!a.ok||c!==r.deviceSessionId||!s||l==null)throw new h(Q(o,`error`)??`LINK_ACCESS_FAILED`,Q(o,`message`)??`링크 리뷰를 시작하지 못했습니다.`,a.status);return{deviceSessionId:c,privateKey:r.privateKey,invitationId:s,expiresAt:l}}async function x(e,t){let n=await e.fetcher(`${e.serviceUrl}/v1/reviewer/account/start`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify({reviewLocator:t,pathname:e.request.location.pathname,returnPath:`${e.request.location.pathname}${e.request.location.search??``}`,returnHash:e.request.location.hash??``}),cache:`no-store`,credentials:`omit`,signal:e.request.signal}),r=await Z(n),i=Q(r,`continueUrl`);throw!n.ok||!i||!te(i,e.serviceUrl)?new h(Q(r,`error`)??`ACCOUNT_BRIDGE_FAILED`,Q(r,`message`)??`로그인 상태를 확인하지 못했습니다.`,n.status):((e.navigateToAccountBridge??(e=>{globalThis.location.assign(e)}))(i),new h(`ACCOUNT_BRIDGE_REDIRECT`,`로그인 상태를 확인하는 중입니다.`,0))}async function ee(e,t,n){let r=await e.fetcher(`${e.serviceUrl}/v1/reviewer/account/redeem`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify({assertionToken:t,pathname:e.request.location.pathname,deviceSessionId:n.deviceSessionId,devicePublicKey:n.publicKey}),cache:`no-store`,credentials:`omit`,signal:e.request.signal}),i=await Z(r),a=Q(i,`invitationId`),o=Q(i,`deviceSessionId`),s=V($(i,`expiresAt`));if(!r.ok||o!==n.deviceSessionId||!a||s==null)throw new h(Q(i,`error`)??`ACCOUNT_BRIDGE_FAILED`,Q(i,`message`)??`로그인 계정으로 리뷰를 시작하지 못했습니다.`,r.status);return{deviceSessionId:o,privateKey:n.privateKey,invitationId:a,expiresAt:s}}function te(e,t){try{let n=new URL(e),r=new URL(t);return n.origin===r.origin&&n.pathname===`/v1/reviewer/account/continue`&&n.searchParams.has(`state`)&&n.hash===``}catch{return!1}}async function S(e,n){let r={invitationId:e.request.invitationId,pathname:e.request.location.pathname,signal:e.request.signal};return t(e.request.authHost,e.request.signal,{requestCode:()=>O(e.serviceUrl,e.fetcher,r),verifyCode:(t,i)=>j(e.serviceUrl,e.fetcher,{...r,challengeId:t,code:i,device:n})},e.request.styleNonce)}async function C(e,t,n,r,i,a){let o;try{o=await w(e,t,n.deviceSessionId,r)}catch(e){throw e instanceof h&&[401,403,409,410].includes(e.status)&&await a(),e}let s=await l(n.privateKey,{purpose:`token`,deviceSessionId:n.deviceSessionId,...o,invitationId:r.invitationId,origin:r.origin,pathname:r.pathname},i),c=await t(`${e}/v1/convex/token`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify({invitationId:r.invitationId,origin:r.origin,pathname:r.pathname,deviceSessionId:n.deviceSessionId,proof:{deviceSessionId:n.deviceSessionId,...o,signature:s}}),cache:`no-store`,credentials:`omit`,signal:r.signal}),u=await Z(c),d=Q(u,`token`);if(!c.ok||!d||d.length>16e3)throw[401,403,409,410].includes(c.status)&&await a(),new h(Q(u,`error`)??`CONVEX_AUTH_FAILED`,Q(u,`message`)??`리뷰 인증을 갱신하지 못했습니다.`,c.status);return d}async function w(e,t,n,r,i=`token`){let a=await t(`${e}/v1/convex/token/challenge`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify({deviceSessionId:n,invitationId:r.invitationId,origin:r.origin,pathname:r.pathname,purpose:i}),cache:`no-store`,credentials:`omit`,signal:r.signal}),o=await Z(a),s=Q(o,`challengeId`),c=Q(o,`challenge`),l=$(o,`counter`),u=V($(o,`expiresAt`));if(!a.ok||!s||!c||!Number.isSafeInteger(l)||l<1||u==null)throw new h(Q(o,`error`)??`DEVICE_CHALLENGE_FAILED`,Q(o,`message`)??`리뷰 기기 인증을 시작하지 못했습니다.`,a.status);return{challengeId:s,challenge:c,counter:l,expiresAt:u}}async function T(e,t,n,r,i){let a=await w(e,t,n.deviceSessionId,r,`revoke`),o=await l(n.privateKey,{purpose:`revoke`,deviceSessionId:n.deviceSessionId,...a,invitationId:r.invitationId,origin:r.origin,pathname:r.pathname},i);if(!(await t(`${e}/v1/convex/session/revoke`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify({deviceSessionId:n.deviceSessionId,invitationId:r.invitationId,origin:r.origin,pathname:r.pathname,proof:{deviceSessionId:n.deviceSessionId,...a,signature:o}}),cache:`no-store`,credentials:`omit`,keepalive:!0,signal:r.signal})).ok)throw Error(`Reviewer device revocation failed`)}async function E(e,t,n){let r=await t(`${e}/v1/invitations/redeem-email`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify({invitationId:n.invitationId,emailToken:n.emailToken,pathname:n.pathname,deviceSessionId:n.device.deviceSessionId,devicePublicKey:n.device.publicKey}),cache:`no-store`,credentials:`omit`,signal:n.signal}),i=await Z(r);if(!r.ok)throw new h(Q(i,`error`)??`INVITATION_REDEEM_FAILED`,Q(i,`message`)??`리뷰 초대를 시작하지 못했습니다.`,r.status);let a=Q(i,`deviceSessionId`);if(!a||a!==n.device.deviceSessionId)throw new h(`INVALID_INVITATION_REDEEM_RESPONSE`,`잘못된 초대 인증 응답입니다.`,502);let o=V($(i,`expiresAt`));if(o===null)throw new h(`INVALID_INVITATION_REDEEM_RESPONSE`,`잘못된 초대 인증 응답입니다.`,502);if(o===void 0)throw new h(`INVALID_INVITATION_REDEEM_RESPONSE`,`device session 만료 시각이 필요합니다.`,502);return{deviceSessionId:a,privateKey:n.device.privateKey,expiresAt:o}}async function D(e,t,n){let r=await t(`${e}/v1/invitations/redeem-email`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify({invitationId:n.invitationId,emailToken:n.emailToken,pathname:n.pathname}),cache:`no-store`,credentials:`omit`,signal:n.signal}),i=await Z(r),a=Q(i,`refreshToken`);if(!r.ok||!a||a.length>4096)throw new h(Q(i,`error`)??`INVITATION_REDEEM_FAILED`,Q(i,`message`)??`리뷰 초대를 시작하지 못했습니다.`,r.status);return{refreshToken:a}}async function O(e,t,n){let r=await M(e,t,`start`,n),i=Q(r,`challengeId`),a=Q(r,`emailHint`);if(!i||!a)throw new h(`INVALID_RECOVERY_RESPONSE`,`잘못된 복구 응답입니다.`,502);return{challengeId:i,emailHint:a}}async function k(e,t,n){let r=await N(e,t,`start`,n),i=Q(r,`challengeId`),a=Q(r,`attemptId`),o=Q(r,`emailHint`);if(!i||!a||!o)throw new h(`INVALID_PROJECT_ACCESS_RESPONSE`,`프로젝트 리뷰 인증 응답이 올바르지 않습니다.`,502);return{challengeId:i,attemptId:a,emailHint:o}}async function A(e,t,n){let r=await N(e,t,`verify`,n),i=Q(r,`deviceSessionId`),a=Q(r,`invitationId`),o=V($(r,`expiresAt`));if(i!==n.device.deviceSessionId||!a||o==null)throw new h(`INVALID_PROJECT_ACCESS_RESPONSE`,`프로젝트 리뷰 인증 응답이 올바르지 않습니다.`,502);return{deviceSessionId:i,privateKey:n.device.privateKey,invitationId:a,expiresAt:o}}async function j(e,t,n){let r=await M(e,t,`verify`,n),i=Q(r,`deviceSessionId`);if(!i||i!==n.device.deviceSessionId)throw new h(`INVALID_RECOVERY_RESPONSE`,`잘못된 복구 응답입니다.`,502);let a=V($(r,`expiresAt`));if(a===null)throw new h(`INVALID_RECOVERY_RESPONSE`,`잘못된 복구 응답입니다.`,502);if(a===void 0)throw new h(`INVALID_RECOVERY_RESPONSE`,`device session 만료 시각이 필요합니다.`,502);return{deviceSessionId:i,privateKey:n.device.privateKey,expiresAt:a}}async function M(e,t,n,r){let{signal:i,...a}=r,o=a;if(`device`in a&&P(a.device)){let{device:e,...t}=a;o={...t,deviceSessionId:e.deviceSessionId,devicePublicKey:e.publicKey}}let s=await t(`${e}/v1/invitations/recovery/${n}`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify(o),cache:`no-store`,credentials:`omit`,signal:i}),c=await Z(s);if(!s.ok)throw new h(Q(c,`error`)??`RECOVERY_FAILED`,Q(c,`message`)??`리뷰 접속을 복구하지 못했습니다.`,s.status);if(!c||typeof c!=`object`||Array.isArray(c))throw new h(`INVALID_RECOVERY_RESPONSE`,`잘못된 복구 응답입니다.`,502);return c}async function N(e,t,n,r){let{signal:i,...a}=r,o=a;if(`device`in a&&P(a.device)){let{device:e,...t}=a;o={...t,deviceSessionId:e.deviceSessionId,devicePublicKey:e.publicKey}}let s=await t(`${e}/v1/reviewer/access/${n}`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify(o),cache:`no-store`,credentials:`omit`,signal:i}),c=await Z(s);if(!s.ok)throw new h(Q(c,`error`)??`PROJECT_ACCESS_FAILED`,Q(c,`message`)??`프로젝트 리뷰에 로그인하지 못했습니다.`,s.status);if(!c||typeof c!=`object`||Array.isArray(c))throw new h(`INVALID_PROJECT_ACCESS_RESPONSE`,`프로젝트 리뷰 인증 응답이 올바르지 않습니다.`,502);return c}function P(e){return!!(e&&typeof e==`object`&&`deviceSessionId`in e&&`privateKey`in e&&`publicKey`in e)}function F(e){return{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname}}async function I(e,t,n){let r=await t(`${e}/v1/pages/resolve`,{method:`POST`,headers:{accept:`application/json`,authorization:`Bearer ${n.refreshToken}`,"content-type":`application/json`},body:JSON.stringify({invitationId:n.invitationId,origin:n.origin,pathname:n.pathname}),cache:`no-store`,credentials:`omit`,signal:n.signal});if(r.ok)return;let i=await Z(r);throw new h(Q(i,`error`)??`PAGE_RESOLVE_FAILED`,Q(i,`message`)??`리뷰 페이지를 준비하지 못했습니다.`,r.status)}async function L(e,t,n,r){let i=await t(`${e}/v1/bootstrap`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify(n),cache:`no-store`,credentials:`omit`,signal:r}),a=await Z(i);if(!i.ok)throw new h(Q(a,`error`)??`BOOTSTRAP_FAILED`,Q(a,`message`)??`Visual Review bootstrap에 실패했습니다.`,i.status);return R(a)}function R(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new h(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let t=e;if(typeof t.apiVersion==`number`&&t.apiVersion!==1&&t.apiVersion!==2)throw new h(`UNSUPPORTED_SERVICE_VERSION`,`이 Visual Review 위젯 버전은 더 이상 지원되지 않습니다. 사이트의 @01.works/visual-review를 업데이트해 주세요.`,502);if(t.apiVersion===2){let e=X(t.convexUrl),n=V(t.invitationExpiresAt),r=z(t.accessScope),i=B(t.sessionLocator);if(t.provider!==`convex`||!e||n===null)throw new h(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{apiVersion:2,provider:`convex`,convexUrl:e,...n===void 0?{}:{invitationExpiresAt:n},...r===void 0?{}:{accessScope:r},...i===void 0?{}:{sessionLocator:i}}}let n=Q(t,`instantAppId`),r=V(t.invitationExpiresAt),i=z(t.accessScope),a=B(t.sessionLocator);if(t.apiVersion!==1||!n||!ne(n)||r===null)throw new h(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{apiVersion:1,instantAppId:n,...r===void 0?{}:{invitationExpiresAt:r},...i===void 0?{}:{accessScope:i},...a===void 0?{}:{sessionLocator:a}}}function z(e){if(e===void 0)return;if(!e||typeof e!=`object`||Array.isArray(e))throw new h(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let t=e,n=Q(t,`locator`);if(t.kind!==`project`||!n||n.length>200||t.mode!==void 0&&t.mode!==`email`&&t.mode!==`link`)throw new h(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{kind:`project`,locator:n,...t.mode===void 0?{}:{mode:t.mode}}}function B(e){if(e!==void 0){if(typeof e!=`string`||!e.trim()||e.length>200)throw new h(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return e.trim()}}function V(e){if(e!==void 0)return Number.isSafeInteger(e)&&e>0?e:null}function H(e,t,n){return`01works.visual-review.convex-session.v1:${JSON.stringify([e,t,n])}`}function U(...e){return e.filter(e=>e!==null)}function W(){try{return globalThis.localStorage??null}catch{return null}}function G(){try{return globalThis.sessionStorage??null}catch{return null}}async function K(e,t,n){try{let t=await e?.get(n);if(t)return t}catch{}let r=t.get(n)??null;return r&&r.expiresAt<=Date.now()?(t.delete(n),null):r}async function q(e,t,n,r){t.set(n,r);try{await e?.set(n,r)}catch{}}async function J(e,t,n){t.delete(n);try{await e?.delete(n)}catch{}}function Y(e,t){for(let n of e)try{n.removeItem(t)}catch{}}function X(e){if(typeof e!=`string`||!e.trim())return null;try{let t=new URL(e.trim());return t.origin!==e.trim()||t.protocol!==`https:`||!t.hostname.endsWith(`.convex.cloud`)?null:t.origin}catch{return null}}async function Z(e){try{return await e.json()}catch{throw new h(`INVALID_BOOTSTRAP_RESPONSE`,`JSON bootstrap 응답이 필요합니다.`,502)}}function Q(e,t){let n=$(e,t);return typeof n==`string`&&n.trim()?n.trim():null}function $(e,t){if(!(!e||typeof e!=`object`||Array.isArray(e)))return e[t]}function ne(e){return/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e)}export{g as createHostedReviewRuntime};
@@ -1,2 +0,0 @@
1
- const e=`https://review.01.works`;function t(e){let t=new URL(e),n=t.hostname===`localhost`||t.hostname===`127.0.0.1`||t.hostname.endsWith(`.test`)||t.hostname.endsWith(`.local`);if(t.protocol!==`https:`&&!(n&&t.protocol===`http:`))throw Error(`Visual Review serviceUrl must use HTTPS outside local development`);if(t.username||t.password||t.search||t.hash)throw Error(`Visual Review serviceUrl must be a plain origin or base path`);return t.toString().replace(/\/+$/,``)}const n=()=>{let e=Promise.resolve(null);return{ready:e,refresh:()=>e,dispose(){}}},r=new Map,i=6e4,a=1e4,o=new WeakMap;function s(e={}){if(e.enabled===!1||typeof window>`u`||typeof document>`u`)return n();let r=!1,i=0,a=null,o=null,s=null,g=null,_=!1,v=!1,y=null,b=null,w=null,D=t(e.serviceUrl??`https://review.01.works`),k=e.activationParam??`visual-review`,j=le(window),N=ue(window),P=C(window.location);if(!(ae(D,k,P,N,j,e.runtime!==void 0)??re(T(D,P.origin)))){let t={reason:`missing-activation`,origin:P.origin};return M(e.build).mode===`development`&&c(document,t.origin),l(e.onInactive,t),n()}let F=new WeakMap,I=new Map,L=fe(e.styleNonce,document),R=x(window.location,k,e.pageIdentity),z=te(window,t=>{let n=x(t,k,e.pageIdentity);if(n===R)return;let r=O(k,t.href)?.invitationId;r&&(v=!1,I.set(t.origin,r)),R=n,V(t)}),B=t=>{if(!(r||!g)){if(t===`membership-revoked`){let e=C(window.location),t=I.get(e.origin);t&&(E(D,e.origin,t),I.delete(e.origin),K(D,e.origin,N,j,t));return}R=x(window.location,k,e.pageIdentity),W()}};return{ready:W(),refresh(){return r?Promise.resolve(null):(R=x(window.location,k,e.pageIdentity),V(C(window.location),!0))},dispose(){r||(r=!0,i+=1,U(),g?.remove(),g=null,w=null,b?.remove(),b=null,I.clear(),y?.dispose(),y=null,z.unsubscribe())}};function V(e,t=!1){return!g||!w||w.origin!==e.origin||O(k,e.href)?.invitationId?W():H(g,w,e,t)}function H(t,n,r,c){let l=++i;a!==o&&a?.abort();let u=new AbortController;a=u,t.beginPageTransition();let d=(async()=>{try{let i=await A(n.resolvePage({location:r,...e.pageIdentity===`url`?{routeKey:S(r)}:{},signal:u.signal,cursorChat:e.cursorChat===!0}),u.signal);return Q(l,u)?(i.commit?.(),t.setPage({pageId:i.pageId,...e.cursorChat===!0?{cursorChat:{roomId:i.cursorChatRoomId}}:{}},{reload:c}),t.isConnected||document.body?.append(t),t):$(l)}catch{return Q(l,u)?W():$(l)}})();return s=d,d}function U(){a?.abort(),o?.abort(),a=null,o=null}function W(){if(v&&!O(k,C(window.location).href))return Promise.resolve(null);let t=++i;U(),y?.suspendSession(),g?.remove(),g=null,w=null,b?.remove();let n=new AbortController,r=document.createElement(`div`);r.dataset.agencyReviewRoot=``,a=n,o=n,b=r;let c=q(t,n,r);return s=c,c.then(r=>{r&&Q(t,n)&&g===r&&e.onReady?.(r)}),c}async function q(t,n,i){try{let e=document.body??await se(document,n.signal);if(!Q(t,n))return $(t);e.append(i);let r=await J(t,n,i);return Q(t,n)?r:(i.remove(),$(t))}catch(a){if(!Q(t,n))return i.remove(),$(t);if(f(a,`AUTH_CANCELLED`)||f(a,`ACCOUNT_BRIDGE_REDIRECT`))return i.remove(),b===i&&(b=null),null;let o=F.get(i),s=o?.[3];if(Z(a,i),p(s)&&f(a,`INVITATION_EMAIL_REQUIRED`)&&!_){let e=o?.[1]??C(window.location).origin,t=o?.[2];return t&&(I.delete(e),K(D,e,N,j,t)),i.remove(),b===i&&(b=null),null}let c=de(a,o?.[2]),u=o?.[1]??C(window.location).origin,d=f(a,`ORIGIN_NOT_ALLOWED`);if(d&&l(e.onInactive,{reason:`origin-not-allowed`,origin:u}),!p(s)||_||!m(a)){let{originNotAllowedMessage:o,renderBootstrapError:s}=await import(`./bootstrap-error-B30Je5Pg.js`);if(!Q(t,n))return i.remove(),$(t);let l=h(a)?void 0:()=>{r||b!==i||(R=x(window.location,k,e.pageIdentity),W())};s(i,d?o(u):c.message,L,l)}else i.remove(),b===i&&(b=null);return e.onError?.(c),window.dispatchEvent(new CustomEvent(`visual-review:error`,{detail:c})),null}}async function J(t,n,r){let i=C(window.location),a=ae(D,k,i,N,j,e.runtime!==void 0),o=ne(I.get(i.origin)),s=re(T(D,i.origin)),c=a?.source===`url`?a:s??o??a;if(!c)return F.delete(r),r.remove(),b===r&&(b=null),null;let l=c.invitationId;F.set(r,[D,i.origin,l,c.source,c.emailToken]),c.source===`url`?(K(D,i.origin,N,j),I.set(i.origin,l),ie(D,i.origin,l,c.emailToken,c.accountToken),z.suppress(()=>oe(k))):c.source===`handoff`&&I.set(i.origin,l),R=x(window.location,k,e.pageIdentity);let f=C(window.location),p=await A((e.runtime??await u(D)).resolve({invitationId:l,emailToken:c.emailToken,accountToken:c.accountToken??void 0,accountBridgeAttempted:c.accountToken!==void 0,location:f,...e.pageIdentity===`url`?{routeKey:S(f)}:{},signal:n.signal,authHost:r,styleNonce:L,cursorChat:e.cursorChat===!0}),n.signal);if(!Q(t,n))return null;E(D,i.origin,l),ce(D,l,i,N,j,p.sessionScope??`browser`,p.sessionExpiresAt),c.source===`url`&&G(j,X(D,i.origin)),I.set(i.origin,l);let m=e.sourceContextResolver??await ee(e.build,n.signal);if(!Q(t,n))return null;let{createActiveReviewSessionLifecycle:h,createReviewNavigationHandler:te,mountReviewWidget:v}=await d(n.signal);if(!Q(t,n))return null;y??=h({window,document,storage:j,onExit:Y,onReauthenticationRequired:B});let O=y.bindSession(l,X(D,i.origin),p.clearLocalSession);return Q(t,n)?(g=v({...p,...e.cursorChat===!0&&p.cursorChatRepository?{cursorChat:{repository:p.cursorChatRepository,roomId:p.cursorChatRoomId}}:{},offset:e.offset,onExitReview:O,onNavigateToFeedback:te(window,e.navigateToFeedback),sourceContextResolver:m,styleNonce:L,position:e.position}),y.attachWidget(g),w=p.resolvePage?{origin:i.origin,resolvePage:e=>p.resolvePage(e)}:null,r.remove(),b===r&&(b=null),_=!0,window.dispatchEvent(new CustomEvent(`visual-review:ready`,{detail:g})),g):null}function Y(e){let t=C(window.location).origin;v=!0,E(D,t,e),I.delete(t),K(D,t,N,j,e),i+=1,U(),g?.remove(),g=null,w=null,b?.remove(),b=null}function Z(e,t){if(!m(e))return;let n=F.get(t);if(!n)return;let[r,i,a]=n;E(r,i,a),I.get(i)===a&&I.delete(i),K(r,i,N,j,a)}function Q(e,t){return!r&&i===e&&a===t&&!t.signal.aborted}function $(e){return!r&&i!==e?s:null}}function c(e,t){let n=o.get(e);n||(n=new Set,o.set(e,n)),!n.has(t)&&(n.add(t),console.info([`[VisualReview] Inactive: no invitation or resume marker was found.`,`Open this page using a Visual Review invitation URL.`,`Current origin: ${t}`].join(`
2
- `)))}function l(e,t){if(e)try{e(t)}catch(e){console.error(`[VisualReview] onInactive callback failed.`,e)}}async function u(e){let{createHostedReviewRuntime:t}=await import(`./hosted-runtime-BFendO_5.js`);return t({serviceUrl:e})}async function d(e){return j(import(`./active-review-mount-BEEKqerS.js`),e,a,`리뷰 위젯을 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`)}async function ee(e,t){let n=M(e),{createEmbeddedSourceContextResolver:r}=await j(import(`./embedded-source-context-BTB3pFqv.js`),t,a,`리뷰 소스 정보를 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`);return r({build:n})}function f(e,t){return e instanceof Error&&`code`in e&&e.code===t}function p(e){return e===`tab-storage`||e===`browser-storage`||e===`legacy-storage`}function m(e){let t=g(e);return typeof t==`string`&&/^INVITATION_(?:EXPIRED|NOT_FOUND|REVOKED)$/.test(t)}function h(e){return m(e)||g(e)===`UNSUPPORTED_SERVICE_VERSION`}function g(e){return e instanceof Error&&`code`in e?e.code:void 0}const _=new WeakMap;function te(e,t){let n=_.get(e);if(!n){let t=e.history,r=t.pushState,i=t.replaceState,a=new Set;n={history:t,originalPushStateDescriptor:Object.getOwnPropertyDescriptor(t,`pushState`),originalReplaceStateDescriptor:Object.getOwnPropertyDescriptor(t,`replaceState`),patchedPushState:function(t,n,i){r.call(this,t,n,i),v(e)},patchedReplaceState:function(t,n,r){i.call(this,t,n,r),v(e)},popstateListener:()=>v(e),subscribers:a,suppressionDepth:0},_.set(e,n),y(t,`pushState`,n.patchedPushState),y(t,`replaceState`,n.patchedReplaceState),e.addEventListener(`popstate`,n.popstateListener)}n.subscribers.add(t);let r=!0;return{suppress(e){n.suppressionDepth+=1;try{return e()}finally{--n.suppressionDepth}},unsubscribe(){r&&(r=!1,n.subscribers.delete(t),!(n.subscribers.size>0)&&(e.removeEventListener(`popstate`,n.popstateListener),b(n.history,`pushState`,n.patchedPushState,n.originalPushStateDescriptor),b(n.history,`replaceState`,n.patchedReplaceState,n.originalReplaceStateDescriptor),_.delete(e)))}}}function v(e){let t=_.get(e);if(!t||t.suppressionDepth>0)return;let n=C(e.location);[...t.subscribers].forEach(e=>e(n))}function y(e,t,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:!0,value:n})}function b(e,t,n,r){if(Object.getOwnPropertyDescriptor(e,t)?.value===n){if(r){Object.defineProperty(e,t,r);return}delete e[t]}}function x(e,t,n){return`${e.origin}\n${n===`url`?S(e):e.pathname}\n${O(t,e.href)?.invitationId??``}`}function S(e){let t=new URL(e.href);return`${t.pathname}${t.search}${t.hash}`}function C(e){return new URL(e.href)}function ne(e){return e?{invitationId:e,source:`memory`}:null}function re(e){return e?{invitationId:e.invitationId,emailToken:e.emailToken,accountToken:e.accountToken,source:`handoff`}:null}function w(e,t){return JSON.stringify([e,t])}function T(e,t,n=Date.now()){let i=w(e,t),a=r.get(i);if(a){if(a.expiresAt>n)return a;clearTimeout(a.timeout),r.delete(i)}}function ie(e,t,n,a,o,s=Date.now()){D(s);let c=w(e,t),l=r.get(c);for(l&&(clearTimeout(l.timeout),r.delete(c));r.size>=32;){let e=r.keys().next().value;if(!e)break;let t=r.get(e);t&&clearTimeout(t.timeout),r.delete(e)}let u=s+i,d=setTimeout(()=>{r.get(c)?.expiresAt===u&&r.delete(c)},i);r.set(c,{invitationId:n,emailToken:a,accountToken:o,expiresAt:u,timeout:d})}function E(e,t,n){let i=w(e,t),a=r.get(i);a?.invitationId===n&&(clearTimeout(a.timeout),r.delete(i))}function D(e){for(let[t,n]of r)n.expiresAt>e||(clearTimeout(n.timeout),r.delete(t))}function ae(e,t,n,r,i,a){let o=O(t,n.href);if(o)return o;let s=U(i,X(e,n.origin)),c=U(r,J(e,n.origin));if(c&&c!==s)return{invitationId:c,source:`tab-storage`};let l=H(i,Y(e,n.origin));if(l&&l.invitationId!==s)return{invitationId:l.invitationId,source:`browser-storage`};let u=U(i,q(e,n.origin));return u&&u!==s?{invitationId:u,source:`legacy-storage`}:a&&Z(n.hostname)?{invitationId:`local-preview`,source:`local-preview`}:null}function O(e,t){let n=new URL(t),r=k(n.hash),i=(r?.get(e)??r?.get(`visual-review`)??r?.get(`agency-review`)??r?.get(`agency-review-invite`)??n.searchParams.get(e)??n.searchParams.get(`agency-review`)??n.searchParams.get(`agency-review-invite`))?.trim();if(!i)return null;let a=r?.get(`visual-review-token`)?.trim(),o=r?.get(`visual-review-account-token`)?.trim();return{invitationId:i,emailToken:a&&/^[\w-]{43}$/.test(a)?a:void 0,accountToken:(o&&o.length<=4096&&/^[\w.-]+$/.test(o)?o:void 0)??(r?.get(`visual-review-account`)===`none`?null:void 0),source:`url`}}function k(e){let t=e.replace(/^#?\??/,``);return t.includes(`=`)?new URLSearchParams(t):null}function oe(e){let t=new URL(window.location.href),n=[e,`visual-review`,`agency-review`,`agency-review-invite`,`visual-review-token`,`visual-review-account-token`,`visual-review-account`,`visual-review-return-hash`];for(let e of n)t.searchParams.delete(e);let r=k(t.hash);if(r){let e=r.get(`visual-review-return-hash`);for(let e of n)r.delete(e);let i=r.toString();t.hash=e!==null&&e.length<=2e3&&(e===``||e[0]===`#`)?e:i?`#${i}`:``}window.history.replaceState(window.history.state,``,`${t.pathname}${t.search}${t.hash}`)}function A(e,t){return new Promise((n,r)=>{let i=()=>r(new DOMException(`Aborted`,`AbortError`));if(t.aborted){i();return}t.addEventListener(`abort`,i,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}function j(e,t,n,r){return new Promise((i,a)=>{let o=!1,s=e=>{o||(o=!0,clearTimeout(l),t.removeEventListener(`abort`,c),e())},c=()=>{s(()=>a(new DOMException(`Aborted`,`AbortError`)))},l=setTimeout(()=>{s(()=>a(Error(r)))},n);if(t.aborted){c();return}t.addEventListener(`abort`,c,{once:!0}),e.then(e=>s(()=>i(e)),e=>s(()=>a(e)))})}function se(e,t){return e.body?Promise.resolve(e.body):t.aborted?Promise.reject(new DOMException(`Aborted`,`AbortError`)):new Promise((n,r)=>{let i=!1,a=new MutationObserver(()=>c()),o=()=>{e.removeEventListener(`DOMContentLoaded`,c),t.removeEventListener(`abort`,l),a.disconnect()},s=e=>{i||(i=!0,o(),e())},c=()=>{let t=e.body;t&&s(()=>n(t))},l=()=>{s(()=>r(new DOMException(`Aborted`,`AbortError`)))};e.addEventListener(`DOMContentLoaded`,c),t.addEventListener(`abort`,l,{once:!0}),a.observe(e,{childList:!0,subtree:!0}),c()})}function M(e){let t=document.querySelector(`meta[name="visual-review-build"]`),n=document.querySelector(`meta[name="visual-review-commit"]`),r=V(F()),i=V(I());return{buildId:B(e?.buildId)??z(t)??r??`unversioned`,gitCommit:L(e,n,i),generatedAt:e?.generatedAt,mode:e?.mode??P(N())??(Z(window.location.hostname)?`development`:`production`)}}function N(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_MODE}catch{return}}function P(e){return e===`development`||e===`preview`||e===`production`?e:void 0}function F(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_ID}catch{return}}function I(){try{return process.env.VISUAL_REVIEW_PUBLIC_GIT_COMMIT}catch{return}}function L(e,t,n){return e?.gitCommit===null?null:typeof e?.gitCommit==`string`?R(e.gitCommit):R(t?.content)??R(n)}function R(e){if(typeof e!=`string`)return null;let t=e.trim().toLowerCase();return/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(t)?t:null}function z(e){return V(e?.content)}function B(e){let t=typeof e==`string`?e.trim():``;return t.length>0?t:null}function V(e){return typeof e==`string`&&e.length>0?e:null}function ce(e,t,n,r,i,a,o){if(a===`tab`){try{r?.setItem(J(e,n.origin),t)}catch{}G(i,Y(e,n.origin))}else{let a=Number.isSafeInteger(o)&&o>Date.now()?o:Date.now()+1440*6e4;try{i?.setItem(Y(e,n.origin),JSON.stringify({version:2,invitationId:t,expiresAt:a}))}catch{}G(r,J(e,n.origin))}W(e,n.origin,i,t)}function H(e,t){let n=U(e,t);if(!n)return null;let r=()=>{try{e?.removeItem?.(t)}catch{}};try{let e=JSON.parse(n),t=e.expiresAt;return e.version!==2||typeof e.invitationId!=`string`||!e.invitationId.trim()||!Number.isSafeInteger(t)||t<=Date.now()?(r(),null):{version:2,invitationId:e.invitationId,expiresAt:t}}catch{return r(),null}}function U(e,t){try{return e?.getItem(t)??null}catch{return null}}function le(e){try{return e.localStorage}catch{return null}}function ue(e){try{return e.sessionStorage}catch{return null}}function W(e,t,n,r){try{if(!n)return;let i=q(e,t),a=n.getItem(i);if(a===null||r!==void 0&&a!==r)return;n.removeItem(i)}catch{}}function G(e,t){try{e?.removeItem(t)}catch{}}function K(e,t,n,r,i){W(e,t,r,i);let a=J(e,t),o=Y(e,t);if(i===void 0){G(n,a),G(r,o);return}U(n,a)===i&&G(n,a),H(r,o)?.invitationId===i&&G(r,o)}function q(e,t){return`visual-review:${e}:${t}:invitation`}function J(e,t){return`visual-review:${e}:${t}:invitation:tab:v2`}function Y(e,t){return`visual-review:${e}:${t}:invitation:browser:v2`}function X(e,t){return`visual-review:${e}:${t}:exit:v1`}function Z(e){return e===`localhost`||e===`127.0.0.1`||e.endsWith(`.test`)||e.endsWith(`.local`)}function de(e,t){let n=e instanceof Error?e.message:String(e),r=Error(Q(n,t));if(e&&typeof e==`object`){let n=`code`in e?e.code:void 0,i=`status`in e?e.status:void 0;typeof n==`string`&&Object.defineProperty(r,"code",{configurable:!0,enumerable:!0,value:Q(n,t)}),typeof i==`number`&&Number.isFinite(i)&&Object.defineProperty(r,"status",{configurable:!0,enumerable:!0,value:i})}return r}function Q(e,t){if(!t)return e;let n=new Set([t,encodeURIComponent(t)]),r=e;for(let e of n)e&&(r=r.split(e).join(`[redacted]`));return r}function fe(e,t){if(e!==void 0)return pe(e);let n=t.currentScript,r=n?$(n):void 0;if(r)return r;try{for(let e of t.querySelectorAll(`script[nonce],style[nonce]`)){let t=$(e);if(t)return t}}catch{}}function $(e){let t=`nonce`in e?e.nonce:void 0;return typeof t==`string`?pe(t):void 0}function pe(e){return e.trim()||void 0}export{e as n,t as r,s as t};
@@ -1 +0,0 @@
1
- import{a as e,c as t,i as n,o as r,r as i,s as a,t as o}from"./src-CjYM9---.js";import{a as s,n as c,t as l}from"./reviewer-auth-presentation-CAm-YbaR.js";import{i as u,init as d}from"@instantdb/core";new Uint8Array([107,167,184,17,157,173,17,209,128,180,0,192,79,212,48,200]);const f=u.schema({entities:{$files:u.entity({path:u.string().unique().indexed(),url:u.string()}),$users:u.entity({email:u.string().unique().indexed()}),projects:u.entity({name:u.string(),slug:u.string().unique().indexed(),allowedOrigin:u.string().optional(),originDisconnectedAt:u.number().optional(),originModelVersion:u.number().optional(),createdAt:u.number().indexed(),updatedAt:u.number()}),projectOrigins:u.entity({projectId:u.string().indexed(),originKey:u.string().unique().indexed(),origin:u.string().indexed(),label:u.string().optional(),createdAt:u.number().indexed(),updatedAt:u.number()}),reviewPages:u.entity({projectId:u.string().indexed(),autoRegistrationSlot:u.string().unique().indexed().optional(),name:u.string(),pathname:u.string(),stagingOrigin:u.string(),createdAt:u.number().indexed(),updatedAt:u.number()}),reviewPageBuilds:u.entity({projectId:u.string().indexed(),pageId:u.string().unique().indexed(),buildId:u.string(),gitCommit:u.string().optional(),generatedAt:u.number().optional(),mode:u.string(),updatedAt:u.number().indexed()}),reviewers:u.entity({authUserId:u.string().indexed(),projectId:u.string().indexed(),email:u.string().indexed(),displayName:u.string(),role:u.string(),createdAt:u.number()}),reviewerIdentityClaims:u.entity({reviewerId:u.string().unique().indexed(),projectId:u.string().indexed(),authUserId:u.string().indexed(),email:u.string(),displayName:u.string(),role:u.string(),createdAt:u.number()}),invitations:u.entity({projectId:u.string().indexed(),reviewerId:u.string().indexed().optional(),email:u.string().indexed(),status:u.string().indexed(),claimRevision:u.number(),claimedByAuthUserId:u.string().indexed().optional(),expiresAt:u.number().indexed(),createdAt:u.number(),acceptedAt:u.number().optional(),revokedAt:u.number().optional(),emailTokenHash:u.string().optional(),emailSentAt:u.number().optional(),reviewUrl:u.string().optional()}),comments:u.entity({pageId:u.string().indexed(),pageNumber:u.number().optional(),authorId:u.string().indexed(),authorAuthUserId:u.string().indexed(),authorName:u.string(),body:u.string(),bodyContentMarker:u.string().optional(),anchorSelector:u.string().optional(),anchorOffsetX:u.number().optional(),anchorOffsetY:u.number().optional(),anchorViewportX:u.number().optional(),anchorViewportY:u.number().optional(),targetKind:u.string().optional(),targetPageX:u.number().optional(),targetPageY:u.number().optional(),targetWidth:u.number().optional(),targetHeight:u.number().optional(),targetViewportX:u.number().optional(),targetViewportY:u.number().optional(),targetViewportWidth:u.number().optional(),targetViewportHeight:u.number().optional(),targetPageOrigin:u.string().optional(),targetPagePathname:u.string().optional(),targetPageSearch:u.string().optional(),targetPageHash:u.string().optional(),targetPageTitle:u.string().optional(),targetCapturedAt:u.number().optional(),environmentBrowser:u.string().optional(),environmentOperatingSystem:u.string().optional(),environmentDeviceType:u.string().optional(),environmentScreenWidth:u.number().optional(),environmentScreenHeight:u.number().optional(),environmentDevicePixelRatio:u.number().optional(),status:u.string().indexed(),workflowRevision:u.number(),createdAt:u.number().indexed(),updatedAt:u.number().indexed(),resolvedAt:u.number().optional(),resolvedById:u.string().optional(),deletingAt:u.number().optional()}),commentWorkflowClaims:u.entity({claimKey:u.string().unique().indexed(),commentId:u.string().indexed(),expectedWorkflowRevision:u.number(),createdAt:u.number().indexed()}),commentPageNumberClaims:u.entity({claimKey:u.string().unique().indexed(),pageId:u.string().indexed(),pageNumber:u.number(),commentId:u.string().indexed(),createdAt:u.number().indexed()}),commentTargetElements:u.entity({commentId:u.string().indexed(),slotKey:u.string().unique().indexed().optional(),ordinal:u.number(),selector:u.string(),tagName:u.string(),textPreview:u.string(),pageX:u.number(),pageY:u.number(),width:u.number(),height:u.number(),viewportX:u.number(),viewportY:u.number(),viewportWidth:u.number(),viewportHeight:u.number(),authorAuthUserId:u.string().indexed()}),commentScopeEntries:u.entity({commentId:u.string().indexed(),slotKey:u.string().unique().indexed().optional(),ordinal:u.number(),key:u.string(),valueType:u.string(),stringValue:u.string().optional(),numberValue:u.number().optional(),booleanValue:u.boolean().optional(),authorAuthUserId:u.string().indexed()}),commentSourceContexts:u.entity({commentId:u.string().unique().indexed(),pageId:u.string().indexed(),authorAuthUserId:u.string().indexed(),contextJson:u.string(),requestPayloadHash:u.string().optional(),createdAt:u.number().indexed()}),replies:u.entity({pageId:u.string().indexed(),commentId:u.string().indexed(),authorId:u.string().indexed(),authorAuthUserId:u.string().indexed(),authorName:u.string(),body:u.string(),bodyContentMarker:u.string().optional(),requestPayloadHash:u.string().optional(),createdAt:u.number().indexed(),updatedAt:u.number().indexed()})},links:{projectOwners:{forward:{on:`projects`,has:`many`,label:`owners`},reverse:{on:`$users`,has:`many`,label:`ownedProjects`}},projectPages:{forward:{on:`projects`,has:`many`,label:`pages`},reverse:{on:`reviewPages`,has:`one`,label:`project`}},projectOriginProject:{forward:{on:`projects`,has:`many`,label:`origins`},reverse:{on:`projectOrigins`,has:`one`,label:`project`}},pageCurrentBuild:{forward:{on:`reviewPageBuilds`,has:`one`,label:`page`,required:!0,onDelete:`cascade`},reverse:{on:`reviewPages`,has:`one`,label:`currentBuild`}},projectReviewers:{forward:{on:`projects`,has:`many`,label:`reviewers`},reverse:{on:`reviewers`,has:`one`,label:`project`}},reviewerUser:{forward:{on:`reviewers`,has:`one`,label:`$user`},reverse:{on:`$users`,has:`many`,label:`reviewerMemberships`}},projectInvitations:{forward:{on:`projects`,has:`many`,label:`invitations`},reverse:{on:`invitations`,has:`one`,label:`project`}},invitationReviewer:{forward:{on:`invitations`,has:`one`,label:`reviewer`},reverse:{on:`reviewers`,has:`many`,label:`acceptedInvitations`}},invitationActiveUser:{forward:{on:`invitations`,has:`one`,label:`activeUser`},reverse:{on:`$users`,has:`many`,label:`activeReviewInvitations`}},pageComments:{forward:{on:`reviewPages`,has:`many`,label:`comments`},reverse:{on:`comments`,has:`one`,label:`page`}},commentReplies:{forward:{on:`comments`,has:`many`,label:`replies`},reverse:{on:`replies`,has:`one`,label:`comment`,required:!0,onDelete:`cascade`}},commentTargetElements:{forward:{on:`commentTargetElements`,has:`one`,label:`comment`,required:!0,onDelete:`cascade`},reverse:{on:`comments`,has:`many`,label:`targetElements`}},commentScopeEntries:{forward:{on:`commentScopeEntries`,has:`one`,label:`comment`,required:!0,onDelete:`cascade`},reverse:{on:`comments`,has:`many`,label:`scopeEntries`}},commentSourceContext:{forward:{on:`commentSourceContexts`,has:`one`,label:`comment`,required:!0,onDelete:`cascade`},reverse:{on:`comments`,has:`one`,label:`sourceContext`}},pageSourceContexts:{forward:{on:`commentSourceContexts`,has:`one`,label:`page`,required:!0},reverse:{on:`reviewPages`,has:`many`,label:`sourceContexts`}},sourceContextAuthor:{forward:{on:`commentSourceContexts`,has:`one`,label:`author`,required:!0},reverse:{on:`reviewers`,has:`many`,label:`sourceContexts`}},commentAuthor:{forward:{on:`comments`,has:`one`,label:`author`},reverse:{on:`reviewers`,has:`many`,label:`comments`}},replyAuthor:{forward:{on:`replies`,has:`one`,label:`author`},reverse:{on:`reviewers`,has:`many`,label:`replies`}}}}),p={$default:`false`},m={$default:`false`},h=`$user.activeReviewInvitations`,g=`${h}.project.id`;function _(e){return[`auth.id != null`,`size(auth.ref('${h}.id')) > 0`,`size(auth.ref('${g}')) == size(auth.ref('${h}.id'))`,`size(auth.ref('${h}.status')) == size(auth.ref('${h}.id'))`,`size(auth.ref('${h}.expiresAt')) == size(auth.ref('${h}.id'))`,`size(auth.ref('${h}.revokedAt')) == 0`,`auth.ref('${h}.status').all(status, status == 'accepted')`,`auth.ref('${h}.expiresAt').all(expiresAt, request.time < timestamp(expiresAt))`,e].join(` && `)}function v(...e){return e.map(e=>`(${e})`).join(` && `)}function y(...e){return e.map(e=>`(${e})`).join(` || `)}function b(e){let t=`data.ref('${e}project.origins.origin')`,n=`data.ref('${e}project.allowedOrigin')`,r=`data.ref('${e}project.originModelVersion')`;return y(`request.origin in ${t}`,v(`size(${r}) == 0`,`request.origin in ${n}`))}_(`data.ref('project.id')[0] in auth.ref('${g}')`),y(`request.origin in data.ref('project.origins.origin')`,v(`size(data.ref('project.originModelVersion')) == 0`,`request.origin in data.ref('project.allowedOrigin')`)),y(`request.origin in data.ref('origins.origin')`,v(`size(data.ref('originModelVersion')) == 0`,`request.origin in data.ref('allowedOrigin')`)),_(`data.ref('page.project.id')[0] in auth.ref('${g}')`),b(`page.`),y(`auth.id != null && auth.id in data.ref('comment.page.project.owners.id')`,v(_(`data.ref('comment.page.project.id')[0] in auth.ref('${g}')`),b(`comment.page.`))),_(`data.ref('comment.page.project.id')[0] in auth.ref('${g}')`),b(`comment.page.`),b(``);const x=v(`data.reviewerId != null`,`data.projectId in data.ref('project.id')`,`data.reviewerId in data.ref('reviewer.id')`,`data.projectId in data.ref('reviewer.project.id')`,`auth.id in data.ref('reviewer.$user.id')`,`auth.email in data.ref('reviewer.email')`);v(`auth.id != null`,`data.revokedAt == null`,`data.status in ['pending', 'accepted']`,`data.status == 'pending' || data.claimedByAuthUserId == auth.id`,`request.time < timestamp(data.expiresAt)`,`request.modifiedFields.all(field, field in ['status', 'claimedByAuthUserId', 'acceptedAt', 'claimRevision', 'activeUser'])`,`'status' in request.modifiedFields`,`'claimedByAuthUserId' in request.modifiedFields`,`'acceptedAt' in request.modifiedFields`,`'claimRevision' in request.modifiedFields`,`'activeUser' in request.modifiedFields`,`newData.status == 'accepted'`,`newData.claimedByAuthUserId == auth.id`,`newData.claimRevision == data.claimRevision + 1`,`math.abs((request.time - timestamp(newData.acceptedAt)).getMinutes()) <= 1`,x),v(`actions.data == 'update'`,`actions.linkedData == 'update'`,`auth.id != null`,`auth.email != null`,`linkedData.id == auth.id`,`linkedData.email == auth.email`,`data.email == auth.email`,`data.revokedAt == null`,`data.status in ['pending', 'accepted']`,`data.status == 'pending' || data.claimedByAuthUserId == auth.id`,`request.time < timestamp(data.expiresAt)`,`newData.status == 'accepted'`,`newData.claimedByAuthUserId == auth.id`,`newData.claimRevision == data.claimRevision + 1`,`math.abs((request.time - timestamp(newData.acceptedAt)).getMinutes()) <= 1`,x),v(`actions.data == 'update'`,`actions.linkedData == 'update'`,`auth.id != null`,`auth.email != null`,`data.id == auth.id`,`data.email == auth.email`,`linkedData.email == auth.email`,`linkedData.revokedAt == null`,`linkedData.status == 'accepted'`,`linkedData.claimedByAuthUserId == auth.id`,`request.time < timestamp(linkedData.expiresAt)`,`math.abs((request.time - timestamp(linkedData.acceptedAt)).getMinutes()) <= 1`,`linkedData.projectId in linkedData.ref('project.id')`,`linkedData.reviewerId in linkedData.ref('reviewer.id')`,`linkedData.projectId in linkedData.ref('reviewer.project.id')`,`auth.id in linkedData.ref('reviewer.$user.id')`,`auth.email in linkedData.ref('reviewer.email')`),v(`auth.id != null`,`auth.email != null`,`linkedData.id == auth.id`,`linkedData.email == auth.email`,`data.email == auth.email`,`data.claimedByAuthUserId == auth.id`,`auth.id in data.ref('activeUser.id')`),v(`auth.id != null`,`auth.email != null`,`data.id == auth.id`,`data.email == auth.email`,`linkedData.email == auth.email`,`linkedData.claimedByAuthUserId == auth.id`,`auth.id in linkedData.ref('activeUser.id')`),{...p},{...p},{...m},{...m},_(`data.id in auth.ref('${g}')`),{...p},{...m},{...p},{...p},{...m},{...p},{...m},_(`data.ref('project.id')[0] in auth.ref('${g}')`),{...p},{...m},{...p},{...p},{...m},{...m},{...p},{...m},{...p},{...p},{...p},{...p},{...p},{...p};function ee(e){if(!e.trim())throw Error(`InstantDB app ID is required`);return d({appId:e,schema:f,devtool:!1})}var te=class{db;session;#e;attachScreenshot;constructor(e,t,n={}){this.db=e,this.session=t,this.#e=n.commentTransport,this.#e&&(this.attachScreenshot=(e,t,n)=>this.#e.uploadScreenshot({pageId:e,commentId:t,screenshot:n}))}async getSnapshot(e){let{data:t}=await this.db.queryOnce(S(e,this.session.authUserId));return w(e,t.comments,t.replies)}async getProjectSnapshot(e){this.#t(e);let{data:t}=await this.db.queryOnce(C(e,this.session.authUserId));return T(e,t.comments,t.replies)}subscribe(e,t,n){return this.db.subscribeQuery(S(e,this.session.authUserId),r=>{if(r.error){n?.(M(r.error));return}if(r.data)try{t(w(e,r.data.comments,r.data.replies))}catch{n?.({type:`error`,code:`data-integrity`,recovery:`retry`,clearSnapshot:!0})}})}subscribeProject(e,t,n){return this.#t(e),this.db.subscribeQuery(C(e,this.session.authUserId),r=>{if(r.error){n?.(M(r.error));return}if(r.data)try{t(T(e,r.data.comments,r.data.replies))}catch{n?.({type:`error`,code:`data-integrity`,recovery:`retry`,clearSnapshot:!0})}})}async mutate(e,t){switch(t.type){case`comment.upsert`:{if(t.comment.pageId!==e)throw Error(`Comment page mismatch`);let n=t.comment;if(n.authorId!==this.session.reviewerId)throw Error(`Comment author mismatch`);let i=a(n.body).trim(),s=R(n.createdAt,`Comment createdAt`);if(R(n.updatedAt,`Comment updatedAt`)<s)throw new o(`Comment updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new o(`Comment edits must go through the review service`);if(n.status!==`open`||n.resolvedAt!==void 0||n.resolvedById!==void 0)throw new o(`New comments must start open`);let c=r(n.target);if(!k(n.anchor,c.publicTarget.anchor))throw new o(`Comment anchor does not match its target`);if(!this.#e)throw new o(`Comment creation requires the review service transport`);await this.#e.createComment({pageId:e,commentId:n.id,body:i,target:n.target,...n.scope===void 0?{}:{scope:n.scope}});return}case`comment.delete`:throw new o(`Comment deletion must go through the review service`);case`reply.upsert`:{let e=t.reply;if(e.authorId!==this.session.reviewerId)throw Error(`Reply author mismatch`);let n=a(e.body,`Reply body`).trim(),r=R(e.createdAt,`Reply createdAt`);if(R(e.updatedAt,`Reply updatedAt`)<r)throw new o(`Reply updatedAt precedes createdAt`);if(e.createdAt!==e.updatedAt)throw new o(`Reply edits must go through the review service`);if(!this.#e)throw new o(`Reply creation requires the review service transport`);await this.#e.createReply({commentId:e.commentId,replyId:e.id,body:n});return}case`reply.delete`:throw new o(`Reply deletion must go through the review service`)}}#t(e){if(!e.trim()||e!==this.session.projectId)throw Error(`Project does not belong to the reviewer session`)}};function S(e,t){return{comments:{$:{where:{pageId:e},order:{createdAt:`asc`}},targetElements:{},scopeEntries:{}},replies:{$:{where:{pageId:e},order:{createdAt:`asc`}}},$users:{$:{where:{id:t}},activeReviewInvitations:{project:{}}}}}function C(e,t){return{comments:{$:{where:{"page.project.id":e},order:{createdAt:`asc`}},page:{project:{}},targetElements:{},scopeEntries:{}},replies:{$:{where:{"comment.page.project.id":e},order:{createdAt:`asc`}},comment:{page:{project:{}}}},$users:{$:{where:{id:t}},activeReviewInvitations:{project:{}}}}}function w(e,t,n){let r=t.map(t=>D(t,e));j(r,`comment`);let i=new Set(r.map(({id:e})=>e)),a=n.map(t=>O(t,e));j(a,`reply`);for(let e of a)if(!i.has(e.commentId))throw new o(`Reply ${e.id} references a comment outside the page snapshot`);return{pageId:e,comments:r,replies:a}}function T(e,t,n){let r=new Map,i=t.map(t=>{let n=I(t.pageId,`comment pageId`);E(t.page,n,e,`comment ${String(t.id)}`);let i=P(t.page,`comment ${String(t.id)} page`),a=D(t,n),o=`/`;try{o=new URL(a.target.pageUrl).pathname||`/`}catch{}return r.set(n,{id:n,name:typeof i.name==`string`&&i.name.trim()?i.name.trim():a.target.pageTitle.trim()||o,pathname:typeof i.pathname==`string`&&i.pathname.trim()?i.pathname.trim():o}),a});j(i,`comment`);let a=new Map(i.map(e=>[e.id,e])),s=n.map(t=>{let n=I(t.pageId,`reply pageId`),r=P(t.comment,`reply ${String(t.id)} comment`),i=I(t.commentId,`reply ${String(t.id)} commentId`);if(I(r.id,`reply ${String(t.id)} comment relation id`)!==i)throw new o(`Reply ${String(t.id)} has an inconsistent comment relation`);E(r.page,n,e,`reply ${String(t.id)}`);let s=O(t,n),c=a.get(s.commentId);if(!c||c.pageId!==n)throw new o(`Reply ${s.id} references a comment outside the project snapshot`);return s});return j(s,`reply`),{projectId:e,pages:[...r.values()].sort((e,t)=>e.pathname.localeCompare(t.pathname)||e.id.localeCompare(t.id)),comments:i,replies:s}}function E(e,t,n,r){let i=P(e,`${r} page`);if(I(i.id,`${r} page id`)!==t)throw new o(`${r} escaped its page relation`);if(I(P(i.project,`${r} project`).id,`${r} project id`)!==n)throw new o(`${r} escaped its project scope`)}function D(r,s){let c=P(r,`comment`),l=I(c.id,`comment id`);if(I(c.pageId,`comment ${l} pageId`)!==s)throw new o(`Comment ${l} escaped its page scope`);I(c.authorAuthUserId,`comment ${l} authorAuthUserId`);let u=!(Object.hasOwn(c,`anchor`)&&Object.hasOwn(c,`target`)),d=u?n(c,c.targetElements,`comment ${l} target`):e(c.target,`comment ${l} target`),f=u?{...d.anchor}:ne(c.anchor,`comment ${l} anchor`);if(!k(f,d.anchor))throw new o(`Comment ${l} has inconsistent anchors`);let p=c.status;if(p!==`open`&&p!==`resolved`)throw new o(`Comment ${l} has an invalid status`);let m=R(c.createdAt,`comment ${l} createdAt`),h=R(c.updatedAt,`comment ${l} updatedAt`);if(h<m)throw new o(`Comment ${l} updatedAt precedes createdAt`);let g=re(c.resolvedAt,`comment ${l} resolvedAt`),_=ie(c.resolvedById,`comment ${l} resolvedById`);if(p===`open`&&(g!==void 0||_!==void 0))throw new o(`Open comment ${l} contains resolution metadata`);if(p===`resolved`&&(g===void 0||_===void 0||g!==h))throw new o(`Resolved comment ${l} has invalid workflow metadata`);return{id:l,pageId:s,...ae(c.pageNumber,`comment ${l} pageNumber`),authorId:I(c.authorId,`comment ${l} authorId`),authorName:I(c.authorName,`comment ${l} authorName`),body:a(c.body,`comment ${l} body`),anchor:f,target:d,...u?A(i(c.scopeEntries)):c.scope==null?{}:{scope:t(c.scope)},status:p,workflowRevision:z(c.workflowRevision,`comment ${l} workflowRevision`),createdAt:m,updatedAt:h,...g===void 0?{}:{resolvedAt:g},..._===void 0?{}:{resolvedById:_}}}function O(e,t){let n=P(e,`reply`),r=I(n.id,`reply id`);if(I(n.pageId,`reply ${r} pageId`)!==t)throw new o(`Reply ${r} escaped its page scope`);I(n.authorAuthUserId,`reply ${r} authorAuthUserId`);let i=R(n.createdAt,`reply ${r} createdAt`),s=R(n.updatedAt,`reply ${r} updatedAt`);if(s<i)throw new o(`Reply ${r} updatedAt precedes createdAt`);return{id:r,commentId:I(n.commentId,`reply ${r} commentId`),authorId:I(n.authorId,`reply ${r} authorId`),authorName:I(n.authorName,`reply ${r} authorName`),body:a(n.body,`reply ${r} body`),createdAt:i,updatedAt:s}}function ne(e,t){let n=P(e,t);if(Object.keys(n).length!==5||!Object.hasOwn(n,`selector`)||!Object.hasOwn(n,`offsetX`)||!Object.hasOwn(n,`offsetY`)||!Object.hasOwn(n,`viewportX`)||!Object.hasOwn(n,`viewportY`))throw new o(`${t} has invalid fields`);return{selector:F(n.selector,`${t} selector`),offsetX:L(n.offsetX,`${t} offsetX`),offsetY:L(n.offsetY,`${t} offsetY`),viewportX:L(n.viewportX,`${t} viewportX`),viewportY:L(n.viewportY,`${t} viewportY`)}}function k(e,t){return e.selector===t.selector&&e.offsetX===t.offsetX&&e.offsetY===t.offsetY&&e.viewportX===t.viewportX&&e.viewportY===t.viewportY}function A(e){return e===void 0?{}:{scope:e}}function j(e,t){let n=new Set;for(let r of e){if(n.has(r.id))throw new o(`Duplicate ${t} ${r.id}`);n.add(r.id)}}function M(e){let t=N(e).toLowerCase();return t.includes(`expired`)||t.includes(`token`)?{type:`access-lost`,code:`session-expired`,recovery:`reauthenticate`,clearSnapshot:!0}:t.includes(`permission`)||t.includes(`forbidden`)||t.includes(`unauthorized`)?{type:`access-lost`,code:`permission-denied`,recovery:`reauthenticate`,clearSnapshot:!0}:{type:`error`,code:`transport`,recovery:`retry`,clearSnapshot:!0}}function N(e){return e instanceof Error?e.message:e&&typeof e==`object`&&`message`in e?String(e.message):``}function P(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new o(`${t} is missing or invalid`);return e}function F(e,t){if(typeof e!=`string`)throw new o(`${t} is invalid`);return e}function I(e,t){let n=F(e,t);if(!n.trim())throw new o(`${t} is empty`);return n}function L(e,t){if(typeof e!=`number`||!Number.isFinite(e)||e<0||e>1)throw new o(`${t} is invalid`);return e}function R(e,t){if(!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw new o(`${t} is invalid`);return e}function z(e,t){if(!Number.isSafeInteger(e)||e<0)throw new o(`${t} is invalid`);return e}function re(e,t){return e==null?void 0:R(e,t)}function ie(e,t){return e==null?void 0:I(e,t)}function ae(e,t){if(e==null)return{};let n=z(e,t);if(n<1)throw new o(`${t} is invalid`);return{pageNumber:n}}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`}),Object.freeze({comments:200,replies:1e3,sourceContexts:200}),Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`});var B=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewerCommentSaveError`}};function oe(e,t){let n=e.replace(/\/+$/,``),r=async(e,r)=>{let i=await t();if(!i)throw new B(`AUTH_REQUIRED`,`로그인 세션이 만료되었습니다. 새로고침 후 다시 시도해 주세요.`);let a;try{a=await fetch(`${n}${e}`,{method:`POST`,headers:{authorization:`Bearer ${i}`,"content-type":`application/json`},body:JSON.stringify(r)})}catch{throw new B(`NETWORK`,`리뷰 서버에 연결하지 못했습니다. 연결을 확인하고 다시 시도해 주세요.`)}if(!a.ok)throw new B(...await V(a))};return{createComment:({target:e,...t})=>{let{environment:n,...i}=e;return r(`/v1/comments`,{...t,target:i,...n?{environment:n}:{}})},createReply:e=>r(`/v1/replies`,e),uploadScreenshot:async({pageId:e,commentId:r,screenshot:i})=>{let a=await t();if(!a)throw new B(`AUTH_REQUIRED`,`로그인 세션이 만료되어 위치 캡처를 저장하지 못했습니다.`);let o;try{o=await fetch(`${n}/v1/comments/${encodeURIComponent(r)}/screenshot`,{method:`PUT`,headers:{authorization:`Bearer ${a}`,"content-type":i.contentType,"x-review-page-id":e,"x-review-image-width":String(i.width),"x-review-image-height":String(i.height)},body:se(i.bytes)})}catch{throw new B(`NETWORK`,`리뷰 서버에 연결하지 못해 위치 캡처를 저장하지 못했습니다.`)}if(!o.ok)throw new B(...await V(o))}}}function se(e){let t=new Uint8Array(e.byteLength);return t.set(e),t.buffer}async function V(e){let t=e.status>=500?`리뷰 서버가 코멘트를 저장하지 못했습니다. 잠시 후 다시 시도해 주세요.`:`코멘트를 저장하지 못했습니다.`;try{let n=await e.json();if(!n||typeof n!=`object`)return[`UNKNOWN`,t];let r=n;return[typeof r.error==`string`?r.error:`UNKNOWN`,typeof r.message==`string`&&r.message.trim()?r.message:t]}catch{return[`UNKNOWN`,t]}}function H(e,t={}){let n=e.trim();if(!n)throw Error(`InstantDB app ID is required`);return{async resolve(e){U(e.routeKey,e.location.pathname);let{db:r,user:i}=await W(n,e,t);t.resolveReviewPage&&await t.resolveReviewPage({refreshToken:i.refresh_token,invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname,signal:e.signal});let{data:a}=await r.queryOnce({reviewers:{$:{where:{authUserId:i.id}}},reviewPages:{},invitations:{}}),o=ce(a.invitations,a.reviewers,a.reviewPages,{invitationId:e.invitationId,authUserId:i.id,email:i.email??``,location:e.location,now:Date.now()});if(!o.ok)throw new s(o.code,$(o.code));let c={authUserId:i.id,reviewerId:o.reviewer.id,projectId:o.reviewer.projectId,invitationId:e.invitationId,email:o.reviewer.email||i.email||``,displayName:o.reviewer.displayName||i.email||`Reviewer`,role:o.reviewer.role===`agency`?`agency`:`reviewer`},l=0;return{pageId:o.page.id,resolvePage:async n=>{let i=++l,a=()=>i!==l||n.signal.aborted;if(n.location.origin!==e.location.origin)throw new s(`PAGE_NOT_FOUND`,$(`PAGE_NOT_FOUND`));U(n.routeKey,n.location.pathname);let{data:o}=await r.queryOnce({reviewPages:{$:{where:{projectId:c.projectId}}}});if(a())throw X();let u=Z(n.location.pathname),d=K(o.reviewPages,c.projectId,n.location.origin,u);if(!d&&t.resolveReviewPage){let i=await r.getAuth();if(a())throw X();if(!i?.refresh_token)throw Error(`리뷰 세션이 만료되어 페이지를 등록할 수 없습니다.`);if(await t.resolveReviewPage({refreshToken:i.refresh_token,invitationId:e.invitationId,origin:n.location.origin,pathname:u,signal:n.signal}),a()||({data:o}=await r.queryOnce({reviewPages:{$:{where:{projectId:c.projectId}}}}),a()))throw X();d=K(o.reviewPages,c.projectId,n.location.origin,u)}if(!d)throw new s(`PAGE_NOT_FOUND`,$(`PAGE_NOT_FOUND`));return{pageId:d.id}},session:c,repository:new te(r,c,{...t.serviceUrl===void 0?{}:{commentTransport:oe(t.serviceUrl,async()=>(await r.getAuth())?.refresh_token??null)}}),allowedStagingHosts:[e.location.hostname],sessionScope:`browser`}}}}function U(e,t){if(e!==void 0&&e!==Z(t))throw Error(`Query/hash page identity requires the Convex review runtime.`)}async function W(e,t,n){let r=(n.databaseFactory??ee)(e),i=!!t.emailToken,a;if(t.emailToken){if(!n.redeemEmailInvitation)throw new s(`INVITATION_EMAIL_REQUIRED`,`이 리뷰는 이메일 초대 링크에서만 시작할 수 있습니다.`);await l(t.authHost,t.signal,t.styleNonce);let e=await n.redeemEmailInvitation({invitationId:t.invitationId,emailToken:t.emailToken,origin:t.location.origin,pathname:t.location.pathname,signal:t.signal});await q(t.signal,()=>r.getAuth())&&await q(t.signal,async()=>r.auth.signOut()),await q(t.signal,async()=>r.auth.signInWithToken(e));let i=await q(t.signal,()=>r.getAuth());if(!i)throw Error(`인증 세션을 확인할 수 없습니다.`);a=i}else a=await le(r,t.signal);if(!i)try{await G(n.acceptInvitation,{refreshToken:a.refresh_token,invitationId:t.invitationId,suggestedDisplayName:ue(a.email),authHost:t.authHost,signal:t.signal,styleNonce:t.styleNonce})}catch(e){throw Y(e,`INVITATION_EMAIL_MISMATCH`)?new s(`INVITATION_EMAIL_REQUIRED`,`초대받은 이메일의 링크를 다시 열어 주세요.`):e}return{db:r,user:a}}async function G(e,t){if(!e)return;let n={refreshToken:t.refreshToken,invitationId:t.invitationId,signal:t.signal};try{await e(n);return}catch(e){if(!Y(e,`DISPLAY_NAME_REQUIRED`))throw e}let r=await c(t.authHost,t.signal,t.suggestedDisplayName,t.styleNonce);await e({...n,displayName:r})}function ce(e,t,n,r){let i=e.find(({id:e})=>e===r.invitationId);if(!i||Q(i.email)!==Q(r.email))return{ok:!1,code:`INVITATION_REQUIRED`};if(i.status===`revoked`)return{ok:!1,code:`INVITATION_REVOKED`};if(i.status===`expired`||i.expiresAt<=r.now)return{ok:!1,code:`INVITATION_EXPIRED`};if(i.status!==`accepted`)return{ok:!1,code:`INVITATION_NOT_ACCEPTED`};let a=t.find(e=>e.authUserId===r.authUserId&&e.projectId===i.projectId);if(!a)return{ok:!1,code:`MEMBERSHIP_REQUIRED`};let o=Z(r.location.pathname),s=K(n,i.projectId,r.location.origin,o);return s?{ok:!0,invitation:i,reviewer:a,page:s}:{ok:!1,code:`PAGE_NOT_FOUND`}}function K(e,t,n,r){let i=e.filter(e=>e.projectId===t&&Z(e.pathname)===r),a=i.filter(({stagingOrigin:e})=>e===n);return(a.length>0?a:i).sort((e,t)=>(e.createdAt??2**53-1)-(t.createdAt??2**53-1)||e.id.localeCompare(t.id))[0]}async function le(e,t){let n=await q(t,()=>e.getAuth());if(n)return n;throw new s(`INVITATION_EMAIL_REQUIRED`,`초대받은 이메일의 링크를 열어 주세요.`)}async function q(e,t){J(e);let n=await t();return J(e),n}function J(e){if(e.aborted)throw de()}function ue(e){return e?.split(`@`)[0]?.trim().slice(0,120)??``}function Y(e,t){return!!(e&&typeof e==`object`&&`code`in e&&e.code===t)}function X(){return new DOMException(`Aborted`,`AbortError`)}function de(){return new s(`AUTH_CANCELLED`,`리뷰 로그인이 취소되었습니다.`)}function Z(e){return e.replace(/\/+$/,``)||`/`}function Q(e){return e.trim().toLowerCase()}function $(e){switch(e){case`INVITATION_REQUIRED`:return`현재 계정과 일치하는 리뷰 초대를 찾을 수 없습니다.`;case`INVITATION_NOT_ACCEPTED`:return`아직 수락되지 않은 리뷰 초대입니다.`;case`INVITATION_REVOKED`:return`취소된 리뷰 초대입니다. 계속 검토하려면 담당자에게 다시 요청하세요.`;case`INVITATION_EXPIRED`:return`만료된 리뷰 초대입니다. 담당자에게 새 링크를 요청하세요.`;case`MEMBERSHIP_REQUIRED`:return`이 프로젝트의 reviewer membership이 없습니다.`;case`PAGE_NOT_FOUND`:return`이 페이지는 아직 리뷰 대상이 아닙니다. 담당자에게 문의하세요.`}}export{H as createInstantReviewRuntime};
@@ -1,13 +0,0 @@
1
- var e=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewBootstrapError`}};function t(e,t,n=``,r){if(t.aborted)return Promise.reject(u());let i=a(e);i.replaceChildren(o(i,r),s(i));let c=i.querySelector(`form`),l=c.elements.namedItem(`displayName`),f=i.querySelector(`button`),p=i.querySelector(`.error`);return l.value=n.trim().slice(0,120),l.focus(),l.select(),new Promise((e,n)=>{let r=!1,a=e=>{r||(r=!0,t.removeEventListener(`abort`,o),i.removeEventListener(`keydown`,h),c.removeEventListener(`submit`,m),e())},o=()=>a(()=>n(u())),s=()=>{let t=l.value.trim();if(!t){p.textContent=`이름을 입력해 주세요.`,l.focus();return}if(t.length>120){p.textContent=`이름은 120자 이하여야 합니다.`,l.focus();return}p.textContent=``,f.disabled=!0,c.setAttribute(`aria-busy`,`true`),a(()=>e(t))},m=e=>{e.preventDefault(),s()},h=e=>{let t=e;if(t.key===`Escape`){t.preventDefault(),o();return}if(t.key===`Tab`){d(i,t);return}t.key===`Enter`&&!t.isComposing&&t.target===l&&(t.preventDefault(),s())};t.addEventListener(`abort`,o,{once:!0}),i.addEventListener(`keydown`,h),c.addEventListener(`submit`,m)})}function n(e,t,n){if(t.aborted)return Promise.reject(u());let r=a(e);r.replaceChildren(o(r,n),c(r));let i=r.querySelector(`form`),s=r.querySelector(`button`);return s.focus(),new Promise((e,n)=>{let a=!1,o=e=>{a||(a=!0,t.removeEventListener(`abort`,c),r.removeEventListener(`keydown`,f),i.removeEventListener(`submit`,l),e())},c=()=>o(()=>n(u())),l=t=>{t.preventDefault(),s.disabled=!0,i.setAttribute(`aria-busy`,`true`),o(e)},f=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),c()):t.key===`Tab`&&d(r,t)};t.addEventListener(`abort`,c,{once:!0}),r.addEventListener(`keydown`,f),i.addEventListener(`submit`,l)})}function r(e,t,n,r){if(t.aborted)return Promise.reject(u());let i=a(e),s=o(i,r);return new Promise((e,r)=>{let a=!1,o=null,c=null,f=()=>{o&&c&&o.removeEventListener(`submit`,c),o=null,c=null},p=e=>{a||(a=!0,t.removeEventListener(`abort`,m),i.removeEventListener(`keydown`,h),f(),e())},m=()=>p(()=>r(u())),h=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),m()):t.key===`Tab`&&d(i,t)},g=(e,t)=>{f(),o=e,c=t,e.addEventListener(`submit`,t),i.replaceChildren(s,e)},_=(t,r)=>{let a=i.ownerDocument,o=a.createElement(`form`);o.setAttribute(`role`,`dialog`),o.setAttribute(`aria-modal`,`true`);let s=l(a,`p`,`01.works`,`eyebrow`),c=l(a,`h2`,`이메일 확인`),u=l(a,`p`,`${r.emailHint}로 보낸 6자리 코드를 입력하세요.`,`description`),d=l(a,`label`,`인증 코드`),f=a.createElement(`input`);f.name=`code`,f.inputMode=`numeric`,f.autocomplete=`one-time-code`,f.pattern=`[0-9]{6}`,f.maxLength=6,f.required=!0;let m=l(a,`p`,``,`error`);m.setAttribute(`role`,`alert`);let h=l(a,`button`,`리뷰 시작`);h.type=`submit`,d.append(f),o.append(s,c,u,d,m,h),g(o,i=>{i.preventDefault();let a=f.value.trim();if(!/^\d{6}$/u.test(a)){m.textContent=`6자리 숫자를 입력해 주세요.`;return}h.disabled=!0,o.setAttribute(`aria-busy`,`true`),m.textContent=``,n.verifyCode(r.challengeId,r.attemptId,t,a).then(t=>p(()=>e(t)),e=>{h.disabled=!1,o.removeAttribute(`aria-busy`),m.textContent=e instanceof Error?e.message:`인증 코드를 확인하지 못했습니다.`,f.select()})}),f.focus()},v=i.ownerDocument,y=v.createElement(`form`);y.setAttribute(`role`,`dialog`),y.setAttribute(`aria-modal`,`true`);let b=l(v,`p`,`01.works`,`eyebrow`),x=l(v,`h2`,`리뷰 로그인`),S=l(v,`p`,`초대받은 이메일로 인증 코드를 보내드립니다.`,`description`),C=l(v,`label`,`이메일`),w=v.createElement(`input`);w.name=`email`,w.type=`email`,w.autocomplete=`email`,w.required=!0;let T=l(v,`p`,``,`error`);T.setAttribute(`role`,`alert`);let E=l(v,`button`,`인증 코드 받기`);E.type=`submit`,C.append(w),y.append(b,x,S,C,T,E),g(y,e=>{e.preventDefault();let t=w.value.trim().toLowerCase();if(t.length>320||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/u.test(t)){T.textContent=`유효한 이메일을 입력해 주세요.`;return}E.disabled=!0,y.setAttribute(`aria-busy`,`true`),T.textContent=``,n.requestCode(t).then(e=>_(t,e),e=>{E.disabled=!1,y.removeAttribute(`aria-busy`),T.textContent=e instanceof Error?e.message:`인증 코드를 보내지 못했습니다.`})}),t.addEventListener(`abort`,m,{once:!0}),i.addEventListener(`keydown`,h),i.replaceChildren(s,y),w.focus()})}async function i(e,t,n,r){if(t.aborted)throw u();let i=await n.requestCode();if(t.aborted)throw u();let s=a(e),c=s.ownerDocument.createElement(`form`);c.setAttribute(`role`,`dialog`),c.setAttribute(`aria-modal`,`true`);let f=l(s.ownerDocument,`p`,`01.works`,`eyebrow`),p=l(s.ownerDocument,`h2`,`리뷰 접속 복구`),m=l(s.ownerDocument,`p`,`${i.emailHint}로 보낸 6자리 코드를 입력하세요.`,`description`),h=l(s.ownerDocument,`label`,`복구 코드`),g=s.ownerDocument.createElement(`input`);g.name=`code`,g.inputMode=`numeric`,g.autocomplete=`one-time-code`,g.pattern=`[0-9]{6}`,g.maxLength=6,g.required=!0;let _=l(s.ownerDocument,`p`,``,`error`);_.setAttribute(`role`,`alert`);let v=l(s.ownerDocument,`button`,`접속 복구`);return v.type=`submit`,h.append(g),c.append(f,p,m,h,_,v),s.replaceChildren(o(s,r),c),g.focus(),new Promise((e,r)=>{let a=!1,o=e=>{a||(a=!0,t.removeEventListener(`abort`,l),s.removeEventListener(`keydown`,f),c.removeEventListener(`submit`,p),e())},l=()=>o(()=>r(u())),f=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),l()):t.key===`Tab`&&d(s,t)},p=t=>{t.preventDefault();let r=g.value.trim();if(!/^\d{6}$/.test(r)){_.textContent=`6자리 숫자를 입력해 주세요.`;return}v.disabled=!0,c.setAttribute(`aria-busy`,`true`),_.textContent=``,n.verifyCode(i.challengeId,r).then(t=>o(()=>e(t)),e=>{v.disabled=!1,c.removeAttribute(`aria-busy`),_.textContent=e instanceof Error?e.message:`복구 코드를 확인하지 못했습니다.`,g.select()})};t.addEventListener(`abort`,l,{once:!0}),s.addEventListener(`keydown`,f),c.addEventListener(`submit`,p)})}function a(e){return e.shadowRoot??e.attachShadow({mode:`open`})}function o(e,t){let n=e.ownerDocument.createElement(`style`);return t&&(n.nonce=t),n.textContent=f,n}function s(e){let t=e.ownerDocument,n=t.createElement(`form`);n.setAttribute(`role`,`dialog`),n.setAttribute(`aria-modal`,`true`),n.setAttribute(`aria-labelledby`,`visual-review-name-title`),n.setAttribute(`aria-describedby`,`visual-review-name-description`);let r=l(t,`p`,`01.works`,`eyebrow`),i=l(t,`h2`,`표시 이름`);i.id=`visual-review-name-title`;let a=l(t,`p`,`피드백에 이 이름이 표시됩니다.`,`description`);a.id=`visual-review-name-description`;let o=l(t,`label`,`이름`);o.htmlFor=`visual-review-display-name`;let s=t.createElement(`input`);s.id=`visual-review-display-name`,s.name=`displayName`,s.autocomplete=`name`,s.maxLength=120,s.required=!0;let c=l(t,`p`,``,`error`);c.setAttribute(`role`,`alert`);let u=l(t,`button`,`리뷰 시작`);return u.type=`submit`,n.append(r,i,a,o,s,c,u),n}function c(e){let t=e.ownerDocument,n=t.createElement(`form`);n.setAttribute(`role`,`dialog`),n.setAttribute(`aria-modal`,`true`),n.setAttribute(`aria-labelledby`,`visual-review-invitation-title`),n.setAttribute(`aria-describedby`,`visual-review-invitation-description`);let r=l(t,`p`,`01.works`,`eyebrow`),i=l(t,`h2`,`리뷰 초대`);i.id=`visual-review-invitation-title`;let a=l(t,`p`,`초대받은 프로젝트를 열고 화면에 피드백을 남길 수 있습니다.`,`description`);a.id=`visual-review-invitation-description`;let o=l(t,`button`,`리뷰 시작`);return o.type=`submit`,n.append(r,i,a,o),n}function l(e,t,n,r){let i=e.createElement(t);return i.textContent=n,r&&(i.className=r),i}function u(){return new e(`AUTH_CANCELLED`,`리뷰 로그인이 취소되었습니다.`)}function d(e,t){let n=Array.from(e.querySelectorAll(`input:not([disabled]),button:not([disabled])`)).filter(e=>!e.closest(`[hidden]`));if(n.length===0)return;let r=n[0],i=n.at(-1);t.shiftKey&&e.activeElement===r?(t.preventDefault(),i.focus()):!t.shiftKey&&e.activeElement===i&&(t.preventDefault(),r.focus())}const f=`
2
- :host{all:initial;--vr-panel:#fff;--vr-text:#161616;--vr-muted:#707070;--vr-label:#3f3f3f;--vr-control:#fff;--vr-border:#d9d9d9;--vr-action:#161616;--vr-action-text:#fff;position:fixed;inset:0;z-index:2147483646;display:grid;place-items:center;overflow:auto;padding:8px;box-sizing:border-box;background:rgba(15,15,15,.34);font-family:Inter,ui-sans-serif,system-ui,sans-serif;color:var(--vr-text)}
3
- form{box-sizing:border-box;width:min(320px,calc(100vw - 16px));padding:20px;border:0;border-radius:14px;background:var(--vr-panel);box-shadow:0 18px 56px rgba(0,0,0,.18)}
4
- .eyebrow{margin:0 0 10px;color:var(--vr-muted);font-size:10px;font-weight:700;letter-spacing:.09em;text-transform:uppercase}
5
- h2{margin:0 0 5px;font-size:16px;line-height:1.3;letter-spacing:-.01em}.description{margin:0 0 18px;color:var(--vr-muted);font-size:13px;line-height:1.45}
6
- [hidden]{display:none!important}label{display:grid;gap:6px;margin-top:12px;color:var(--vr-label);font-size:12px;font-weight:600}input{box-sizing:border-box;width:100%;height:40px;margin-top:6px;padding:0 11px;border:1px solid var(--vr-border);border-radius:9px;background:var(--vr-control);color:var(--vr-text);font:400 13px/1 Inter,ui-sans-serif,system-ui,sans-serif}
7
- label input{margin-top:0}input:focus{border-color:#999;outline:0;box-shadow:0 0 0 3px rgba(127,127,127,.16)}.error{min-height:17px;margin:8px 0 0;color:#d92d20;font-size:11px;line-height:1.45}
8
- button{width:100%;height:40px;margin-top:7px;border:0;border-radius:9px;background:var(--vr-action);color:var(--vr-action-text);font:650 13px/1 Inter,ui-sans-serif,system-ui,sans-serif;cursor:pointer}button:focus-visible{outline:2px solid var(--vr-action);outline-offset:2px}button:disabled{opacity:.55;cursor:wait}
9
- @media (prefers-color-scheme:dark){:host{--vr-panel:#161616;--vr-text:#fff;--vr-muted:#a7a7a7;--vr-label:#d6d6d6;--vr-control:#222;--vr-border:#3a3a3a;--vr-action:#fff;--vr-action-text:#171717}}
10
- @media (pointer:coarse){input,button{height:44px}}
11
- @media (max-width:480px){form{padding:18px}input{font-size:16px}}
12
- @media (prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;transition:none!important;animation:none!important}}
13
- `;export{e as a,i,t as n,r,n as t};
@@ -1 +0,0 @@
1
- import{t as e}from"./source-origin-BNA5RIlJ.js";const t=131072,n=32768,r=4096,i=1e3,a=0xe677d21fdbff;var o=class extends Error{constructor(e,t){super(e,t),this.name=`InstantCaptureIntegrityError`}};function s(e){let n=g(e,`comment target`,!0),r={kind:n.kind,anchor:E(n.anchor),region:k(n.region),elements:n.elements.map(e=>({selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,rect:k(e.rect),source:null,componentStack:[]})),pageUrl:n.pageUrl,pageTitle:n.pageTitle,capturedAt:n.capturedAt,...n.environment?{environment:y(n.environment)}:{}},i={elements:n.elements.map(e=>({selector:e.selector,source:e.source?A(e.source):null,componentStack:e.componentStack.map(A)})),...n.sourceProvenance?{sourceProvenance:j(n.sourceProvenance)}:{}};W(r,t,`Public target`);let a=G(i,65536,`Source context`);return{publicTarget:r,commentFields:u(r),targetElements:r.elements.map(d),sourceContextJson:a}}function c(e,t,n){let i=N(e,n),a={selector:F(i.anchorSelector,`${n} anchor selector`,r),offsetX:B(i.anchorOffsetX,`${n} anchor offsetX`),offsetY:B(i.anchorOffsetY,`${n} anchor offsetY`),viewportX:B(i.anchorViewportX,`${n} anchor viewportX`),viewportY:B(i.anchorViewportY,`${n} anchor viewportY`)},o=p({kind:i.targetKind,anchor:a,region:{pageX:i.targetPageX,pageY:i.targetPageY,width:i.targetWidth,height:i.targetHeight,viewportX:i.targetViewportX,viewportY:i.targetViewportY,viewportWidth:i.targetViewportWidth,viewportHeight:i.targetViewportHeight},elements:[],pageUrl:O({origin:L(i.targetPageOrigin,`${n} page origin`,1024),pathname:L(i.targetPagePathname,`${n} page pathname`,4096),search:F(i.targetPageSearch,`${n} page search`,1024),hash:F(i.targetPageHash,`${n} page hash`,1024)}),pageTitle:i.targetPageTitle,capturedAt:i.targetCapturedAt,...v(i,n)},n),s=f(t,`${n} elements`),c=o;for(let e of s)try{c=p({...o,elements:[...c.elements,e]},n)}catch{}return c}function l(e){if(!Array.isArray(e)||e.length===0)return;let t=[...e].map(e=>{try{let t=N(e,`Comment scope entry`);return{row:t,ordinal:z(t.ordinal,`Comment scope entry ordinal`,0,19),id:typeof t.id==`string`?t.id:``}}catch{return null}}).filter(e=>e!==null).sort((e,t)=>e.ordinal-t.ordinal||e.id.localeCompare(t.id)),r={},a=new Set;for(let{row:e,ordinal:n}of t)if(!a.has(n)){a.add(n);try{let t=L(e.key,`Comment scope key`,256);if(Object.hasOwn(r,t))continue;switch(e.valueType){case`string`:r[t]=F(e.stringValue,`Comment scope ${t}`,i);break;case`number`:r[t]=R(e.numberValue,`Comment scope ${t}`);break;case`boolean`:if(typeof e.booleanValue!=`boolean`)throw K(`Comment scope ${t} is invalid`);r[t]=e.booleanValue;break;case`null`:r[t]=null;break;default:throw K(`Comment scope ${t} is invalid`)}}catch{}}if(Object.keys(r).length!==0)try{return W(r,n,`Comment scope`),r}catch{return}}function u(e){let t=new URL(e.pageUrl);return{anchorSelector:e.anchor.selector,anchorOffsetX:e.anchor.offsetX,anchorOffsetY:e.anchor.offsetY,anchorViewportX:e.anchor.viewportX,anchorViewportY:e.anchor.viewportY,targetKind:e.kind,targetPageX:e.region.pageX,targetPageY:e.region.pageY,targetWidth:e.region.width,targetHeight:e.region.height,targetViewportX:e.region.viewportX,targetViewportY:e.region.viewportY,targetViewportWidth:e.region.viewportWidth,targetViewportHeight:e.region.viewportHeight,targetPageOrigin:t.origin,targetPagePathname:D(t.pathname),targetPageSearch:t.search.slice(1),targetPageHash:t.hash.slice(1),targetPageTitle:e.pageTitle,targetCapturedAt:e.capturedAt,...e.environment?{environmentBrowser:e.environment.browser,environmentOperatingSystem:e.environment.operatingSystem,environmentDeviceType:e.environment.deviceType,environmentScreenWidth:e.environment.screenWidth,environmentScreenHeight:e.environment.screenHeight,environmentDevicePixelRatio:e.environment.devicePixelRatio}:{}}}function d(e,t){return{ordinal:t,selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,pageX:e.rect.pageX,pageY:e.rect.pageY,width:e.rect.width,height:e.rect.height,viewportX:e.rect.viewportX,viewportY:e.rect.viewportY,viewportWidth:e.rect.viewportWidth,viewportHeight:e.rect.viewportHeight}}function f(e,t){if(!Array.isArray(e)||e.length===0)return[];let n=[...e].map(e=>{try{let n=N(e,t);return{row:n,ordinal:z(n.ordinal,`${t} ordinal`,0,7),id:typeof n.id==`string`?n.id:``}}catch{return null}}).filter(e=>e!==null).sort((e,t)=>e.ordinal-t.ordinal||e.id.localeCompare(t.id)),r=[],i=new Set;for(let{row:e,ordinal:a}of n)if(!i.has(a)){i.add(a);try{r.push(x({selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,rect:{pageX:e.pageX,pageY:e.pageY,width:e.width,height:e.height,viewportX:e.viewportX,viewportY:e.viewportY,viewportWidth:e.viewportWidth,viewportHeight:e.viewportHeight},source:null,componentStack:[]},`${t}[${a}]`,!1))}catch{}}return r}function p(e,t){return g(e,t,!1)}function m(e,t=`Comment body`){return L(e,t,2e4)}function h(e){if(e==null)return;let t=N(e,`Comment scope`);if(Object.keys(t).length>20)throw K(`Comment scope has too many fields`);let r={};for(let[e,n]of Object.entries(t)){if(!e.trim()||e.length>256)throw K(`Comment scope has an invalid key`);if(typeof n==`string`){if(n.length>i)throw K(`Comment scope ${e} is too long`);r[e]=n}else if(typeof n==`number`)r[e]=R(n,`Comment scope ${e}`);else if(typeof n==`boolean`||n===null)r[e]=n;else throw K(`Comment scope ${e} is invalid`)}return W(r,n,`Comment scope`),r}function g(e,n,r){let a=M(e,n,[`kind`,`anchor`,`region`,`elements`,`pageUrl`,`pageTitle`,`capturedAt`,`environment`,`sourceProvenance`],[`environment`,`sourceProvenance`]),o=a.kind;if(o!==`element`&&o!==`region`&&o!==`viewport`)throw K(`${n} kind is invalid`);let s=P(a.elements,`${n} elements`);if(s.length>8)throw K(`${n} contains too many elements`);if(!r&&a.sourceProvenance!=null)throw K(`${n} exposes source provenance`);let c=L(a.pageUrl,`${n} pageUrl`,8192);U(c,`${n} pageUrl`);let l={kind:o,anchor:S(a.anchor,`${n} anchor`),region:C(a.region,`${n} region`),elements:s.map((e,t)=>x(e,`${n} elements[${t}]`,r)),pageUrl:c,pageTitle:F(a.pageTitle,`${n} pageTitle`,i),capturedAt:V(a.capturedAt,`${n} capturedAt`),...a.environment==null?{}:{environment:_(a.environment,`${n} environment`)},...r&&a.sourceProvenance!=null?{sourceProvenance:T(a.sourceProvenance,`${n} provenance`)}:{}};return W(l,r?196608:t,n),l}function _(e,t){let n=M(e,t,[`browser`,`operatingSystem`,`deviceType`,`screenWidth`,`screenHeight`,`devicePixelRatio`]),r=n.deviceType;if(r!==`desktop`&&r!==`tablet`&&r!==`mobile`&&r!==`unknown`)throw K(`${t} deviceType is invalid`);return{browser:L(n.browser,`${t} browser`,120),operatingSystem:L(n.operatingSystem,`${t} operatingSystem`,120),deviceType:r,screenWidth:b(n.screenWidth,`${t} screenWidth`,1e5),screenHeight:b(n.screenHeight,`${t} screenHeight`,1e5),devicePixelRatio:b(n.devicePixelRatio,`${t} devicePixelRatio`,100)}}function v(e,t){if([e.environmentBrowser,e.environmentOperatingSystem,e.environmentDeviceType,e.environmentScreenWidth,e.environmentScreenHeight,e.environmentDevicePixelRatio].every(e=>e==null))return{};try{return{environment:_({browser:e.environmentBrowser,operatingSystem:e.environmentOperatingSystem,deviceType:e.environmentDeviceType,screenWidth:e.environmentScreenWidth,screenHeight:e.environmentScreenHeight,devicePixelRatio:e.environmentDevicePixelRatio},`${t} environment`)}}catch{return{}}}function y(e){return{...e}}function b(e,t,n){let r=R(e,t);if(r<=0||r>n)throw K(`${t} is invalid`);return r}function x(e,t,n){let a=M(e,t,[`selector`,`tagName`,`textPreview`,`rect`,`source`,`componentStack`]),o=P(a.componentStack,`${t} componentStack`);if(o.length>32)throw K(`${t} componentStack is too large`);if(!n&&(a.source!=null||o.length>0))throw K(`${t} exposes source metadata`);return{selector:L(a.selector,`${t} selector`,r),tagName:L(a.tagName,`${t} tagName`,128),textPreview:F(a.textPreview,`${t} textPreview`,i),rect:C(a.rect,`${t} rect`),source:n&&a.source!=null?w(a.source,`${t} source`):null,componentStack:n?o.map((e,n)=>w(e,`${t} stack[${n}]`)):[]}}function S(e,t){let n=M(e,t,[`selector`,`offsetX`,`offsetY`,`viewportX`,`viewportY`]);return{selector:F(n.selector,`${t} selector`,r),offsetX:B(n.offsetX,`${t} offsetX`),offsetY:B(n.offsetY,`${t} offsetY`),viewportX:B(n.viewportX,`${t} viewportX`),viewportY:B(n.viewportY,`${t} viewportY`)}}function C(e,t){let n=M(e,t,[`pageX`,`pageY`,`width`,`height`,`viewportX`,`viewportY`,`viewportWidth`,`viewportHeight`]),r={pageX:R(n.pageX,`${t} pageX`),pageY:R(n.pageY,`${t} pageY`),width:R(n.width,`${t} width`),height:R(n.height,`${t} height`),viewportX:R(n.viewportX,`${t} viewportX`),viewportY:R(n.viewportY,`${t} viewportY`),viewportWidth:R(n.viewportWidth,`${t} viewportWidth`),viewportHeight:R(n.viewportHeight,`${t} viewportHeight`)};if(r.width<0||r.height<0||r.viewportWidth<0||r.viewportHeight<0)throw K(`${t} has a negative dimension`);return r}function w(t,n){let i=M(t,n,[`filePath`,`lineNumber`,`columnNumber`,`componentName`,`origin`,`generated`],[`generated`]),a=i.origin;if(a!==`app`&&a!==`shared-ui`&&a!==`dependency`&&a!==`generated`&&a!==`unknown`)throw K(`${n} origin is invalid`);let o=L(i.filePath,`${n} filePath`,r);return{filePath:o,lineNumber:H(i.lineNumber,`${n} lineNumber`),columnNumber:H(i.columnNumber,`${n} columnNumber`),componentName:i.componentName==null?null:L(i.componentName,`${n} componentName`,512),origin:e(o)}}function T(e,t){let n=M(e,t,[`provider`,`build`,`resolvedAt`]),r=n.provider;if(r!==`react-grab`&&r!==`embedded`&&r!==`custom`)throw K(`${t} provider is invalid`);let i=M(n.build,`${t} build`,[`buildId`,`gitCommit`,`generatedAt`,`mode`],[`generatedAt`]),a=i.mode;if(a!==`development`&&a!==`preview`&&a!==`production`)throw K(`${t} build mode is invalid`);return{provider:r,build:{buildId:L(i.buildId,`${t} buildId`,512),gitCommit:i.gitCommit==null?null:L(i.gitCommit,`${t} gitCommit`,256),...i.generatedAt==null?{}:{generatedAt:V(i.generatedAt,`${t} generatedAt`)},mode:a},resolvedAt:V(n.resolvedAt,`${t} resolvedAt`)}}function E(e){return{...e}}function D(e){return e.replace(/\/+$/,``)||`/`}function O(e){return`${e.origin}${e.pathname}${e.search?`?${e.search}`:``}${e.hash?`#${e.hash}`:``}`}function k(e){return{...e}}function A(e){return{...e}}function j(e){return{...e,build:{...e.build}}}function M(e,t,n,r=[]){let i=N(e,t);if(Object.keys(i).some(e=>!n.includes(e)))throw K(`${t} contains unknown fields`);for(let e of n)if(!r.includes(e)&&!Object.hasOwn(i,e))throw K(`${t} is missing ${e}`);return i}function N(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw K(`${t} is missing or invalid`);return e}function P(e,t){if(!Array.isArray(e))throw K(`${t} is missing or invalid`);return e}function F(e,t,n){if(typeof e!=`string`||I(e,n)>n)throw K(`${t} is invalid or too long`);return e}function I(e,t){let n=0;for(let r of e)if(n+=1,n>t)return n;return n}function L(e,t,n){let r=F(e,t,n);if(!r.trim())throw K(`${t} is empty`);return r}function R(e,t){if(typeof e!=`number`||!Number.isFinite(e))throw K(`${t} is invalid`);return e}function z(e,t,n,r){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<n||e>r)throw K(`${t} is invalid`);return e}function B(e,t){let n=R(e,t);if(n<0||n>1)throw K(`${t} is outside 0..1`);return n}function V(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw K(`${t} is invalid`);return e}function H(e,t){if(e===null)return null;if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0)throw K(`${t} is invalid`);return e}function U(e,t){let n;try{n=new URL(e)}catch(e){throw K(`${t} is invalid`,e)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw K(`${t} must use HTTP or HTTPS`)}function W(e,t,n){G(e,t,n)}function G(e,t,n){let r;try{r=JSON.stringify(e)}catch(e){throw K(`${n} cannot be serialized`,e)}if(r.length>t)throw K(`${n} is too large`);return r}function K(e,t){return new o(e,{cause:t instanceof Error?t:void 0})}export{p as a,h as c,c as i,a as n,s as o,l as r,m as s,o as t};