@01.works/visual-review 0.9.4 → 0.9.6
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.
- package/README.md +16 -6
- package/dist/active-review-mount-DtVtT0xd.js +1505 -0
- package/dist/{bootstrap-error-BwIf8fUE.js → bootstrap-error-B30Je5Pg.js} +3 -2
- package/dist/{hosted-runtime-BKZERnAW.js → hosted-runtime-D6Xuc19F.js} +2 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1 -1
- package/dist/install-Dh6WT91E.js +2 -0
- package/dist/react.js +1 -1
- package/package.json +1 -1
- package/dist/install-DSA2Fpbw.js +0 -3
- package/dist/src-CtuDVE7s.js +0 -1467
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
function e(e,
|
|
1
|
+
function e(e,t,i,a){let o=e.shadowRoot??e.attachShadow({mode:`open`}),s=o.ownerDocument;e.dataset.vrTheme=n(s);let c=s.createElement(`style`);i&&(c.nonce=i),c.textContent=r;let l=s.createElement(`strong`);l.id=`visual-review-bootstrap-error-title`,l.textContent=`Visual Review를 시작할 수 없습니다`;let u=s.createElement(`span`);u.id=`visual-review-bootstrap-error-description`,u.textContent=t;let d=s.createElement(`span`);d.className=`bootstrap-error-mark`,d.setAttribute(`aria-hidden`,`true`);let f=s.createElement(`span`);f.className=`bootstrap-error-copy`,f.append(l,u);let p=s.createElement(`span`);p.className=`bootstrap-error-content`,p.append(d,f);let m=s.createElement(`button`);m.type=`button`,m.className=`bootstrap-error-retry`,m.textContent=`다시 시도`,a&&m.addEventListener(`click`,()=>{m.disabled=!0,m.textContent=`다시 시도 중…`,g.setAttribute(`aria-busy`,`true`),a()},{once:!0});let h=s.createElement(`button`);h.type=`button`,h.className=`bootstrap-error-dismiss`,h.setAttribute(`aria-label`,`Visual Review 알림 닫기`),h.textContent=`×`,h.addEventListener(`click`,()=>e.remove(),{once:!0});let g=s.createElement(`div`);g.className=`bootstrap-error`,g.setAttribute(`role`,`alert`),g.setAttribute(`aria-labelledby`,l.id),g.setAttribute(`aria-describedby`,u.id),g.append(p),a&&g.append(m),g.append(h),o.replaceChildren(c,g)}function t(e){return[`현재 Origin이 Visual Review 프로젝트에 등록되어 있지 않아 시작할 수 없습니다.`,``,`현재 Origin:`,e,``,`프로젝트 설정에 위 값을 그대로 추가한 다음 초대 링크를 다시 여세요.`,`프로토콜, 호스트 이름, 포트까지 정확히 일치해야 합니다.`].join(`
|
|
2
|
+
`)}function n(e){let t=e.defaultView;if(!t)return`light`;for(let n of[e.body,e.documentElement]){if(!n)continue;let e=t.getComputedStyle(n).backgroundColor.match(/[\d.]+/g)?.map(Number);if(!e||e.length<3)continue;let[r=0,i=0,a=0,o=1]=e;if(!(o<.5))return(r*.2126+i*.7152+a*.0722)/255<.45?`light`:`dark`}return t.matchMedia?.(`(prefers-color-scheme: dark)`).matches??!1?`light`:`dark`}const r=`
|
|
2
3
|
:host {
|
|
3
4
|
all: initial;
|
|
4
5
|
position: fixed;
|
|
@@ -139,4 +140,4 @@ function e(e,r,i,a){let o=e.shadowRoot??e.attachShadow({mode:`open`}),s=o.ownerD
|
|
|
139
140
|
from { opacity: 0; transform: translateY(4px) scale(.985); }
|
|
140
141
|
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
141
142
|
}
|
|
142
|
-
`;export{e as renderBootstrapError};
|
|
143
|
+
`;export{t as originNotAllowedMessage,e as renderBootstrapError};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as e}from"./install-DSA2Fpbw.js";import{t}from"./embedded-source-DSDHbbeU.js";import{i as n,init as r}from"@instantdb/core";import{makeFunctionReference as i}from"convex/server";import{ConvexClient as a}from"convex/browser";const o=131072,s=32768,c=4096,l=1e3;var u=class extends Error{constructor(e,t){super(e,t),this.name=`InstantCaptureIntegrityError`}};function d(e){let t=re(e,`comment target`,!0),n={kind:t.kind,anchor:fe(t.anchor),region:he(t.region),elements:t.elements.map(e=>({selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,rect:he(e.rect),source:null,componentStack:[]})),pageUrl:t.pageUrl,pageTitle:t.pageTitle,capturedAt:t.capturedAt,...t.environment?{environment:oe(t.environment)}:{}},r={elements:t.elements.map(e=>({selector:e.selector,source:e.source?ge(e.source):null,componentStack:e.componentStack.map(ge)})),...t.sourceProvenance?{sourceProvenance:_e(t.sourceProvenance)}:{}};T(n,o,`Public target`);let i=Ce(r,65536,`Source context`);return{publicTarget:n,commentFields:m(n),targetElements:n.elements.map(h),sourceContextJson:i}}function f(e,t,n){let r=y(e,n),i={selector:b(r.anchorSelector,`${n} anchor selector`,c),offsetX:C(r.anchorOffsetX,`${n} anchor offsetX`),offsetY:C(r.anchorOffsetY,`${n} anchor offsetY`),viewportX:C(r.anchorViewportX,`${n} anchor viewportX`),viewportY:C(r.anchorViewportY,`${n} anchor viewportY`)},a=te({kind:r.targetKind,anchor:i,region:{pageX:r.targetPageX,pageY:r.targetPageY,width:r.targetWidth,height:r.targetHeight,viewportX:r.targetViewportX,viewportY:r.targetViewportY,viewportWidth:r.targetViewportWidth,viewportHeight:r.targetViewportHeight},elements:[],pageUrl:me({origin:x(r.targetPageOrigin,`${n} page origin`,1024),pathname:x(r.targetPagePathname,`${n} page pathname`,4096),search:b(r.targetPageSearch,`${n} page search`,1024),hash:b(r.targetPageHash,`${n} page hash`,1024)}),pageTitle:r.targetPageTitle,capturedAt:r.targetCapturedAt,...ae(r,n)},n),o=ee(t,`${n} elements`),s=a;for(let e of o)try{s=te({...a,elements:[...s.elements,e]},n)}catch{}return s}function p(e){if(!Array.isArray(e)||e.length===0)return;let t=[...e].map(e=>{try{let t=y(e,`Comment scope entry`);return{row:t,ordinal:be(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)),n={},r=new Set;for(let{row:e,ordinal:i}of t)if(!r.has(i)){r.add(i);try{let t=x(e.key,`Comment scope key`,256);if(Object.hasOwn(n,t))continue;switch(e.valueType){case`string`:n[t]=b(e.stringValue,`Comment scope ${t}`,l);break;case`number`:n[t]=S(e.numberValue,`Comment scope ${t}`);break;case`boolean`:if(typeof e.booleanValue!=`boolean`)throw E(`Comment scope ${t} is invalid`);n[t]=e.booleanValue;break;case`null`:n[t]=null;break;default:throw E(`Comment scope ${t} is invalid`)}}catch{}}if(Object.keys(n).length!==0)try{return T(n,s,`Comment scope`),n}catch{return}}function m(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:pe(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 h(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 ee(e,t){if(!Array.isArray(e)||e.length===0)return[];let n=[...e].map(e=>{try{let n=y(e,t);return{row:n,ordinal:be(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(se({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 te(e,t){return re(e,t,!1)}function g(e,t=`Comment body`){return x(e,t,2e4)}function ne(e){if(e==null)return;let t=y(e,`Comment scope`);if(Object.keys(t).length>20)throw E(`Comment scope has too many fields`);let n={};for(let[e,r]of Object.entries(t)){if(!e.trim()||e.length>256)throw E(`Comment scope has an invalid key`);if(typeof r==`string`){if(r.length>l)throw E(`Comment scope ${e} is too long`);n[e]=r}else if(typeof r==`number`)n[e]=S(r,`Comment scope ${e}`);else if(typeof r==`boolean`||r===null)n[e]=r;else throw E(`Comment scope ${e} is invalid`)}return T(n,s,`Comment scope`),n}function re(e,t,n){let r=v(e,t,[`kind`,`anchor`,`region`,`elements`,`pageUrl`,`pageTitle`,`capturedAt`,`environment`,`sourceProvenance`],[`environment`,`sourceProvenance`]),i=r.kind;if(i!==`element`&&i!==`region`&&i!==`viewport`)throw E(`${t} kind is invalid`);let a=ve(r.elements,`${t} elements`);if(a.length>8)throw E(`${t} contains too many elements`);if(!n&&r.sourceProvenance!=null)throw E(`${t} exposes source provenance`);let s=x(r.pageUrl,`${t} pageUrl`,8192);Se(s,`${t} pageUrl`);let c={kind:i,anchor:ce(r.anchor,`${t} anchor`),region:le(r.region,`${t} region`),elements:a.map((e,r)=>se(e,`${t} elements[${r}]`,n)),pageUrl:s,pageTitle:b(r.pageTitle,`${t} pageTitle`,l),capturedAt:w(r.capturedAt,`${t} capturedAt`),...r.environment==null?{}:{environment:ie(r.environment,`${t} environment`)},...n&&r.sourceProvenance!=null?{sourceProvenance:de(r.sourceProvenance,`${t} provenance`)}:{}};return T(c,n?196608:o,t),c}function ie(e,t){let n=v(e,t,[`browser`,`operatingSystem`,`deviceType`,`screenWidth`,`screenHeight`,`devicePixelRatio`]),r=n.deviceType;if(r!==`desktop`&&r!==`tablet`&&r!==`mobile`&&r!==`unknown`)throw E(`${t} deviceType is invalid`);return{browser:x(n.browser,`${t} browser`,120),operatingSystem:x(n.operatingSystem,`${t} operatingSystem`,120),deviceType:r,screenWidth:_(n.screenWidth,`${t} screenWidth`,1e5),screenHeight:_(n.screenHeight,`${t} screenHeight`,1e5),devicePixelRatio:_(n.devicePixelRatio,`${t} devicePixelRatio`,100)}}function ae(e,t){if([e.environmentBrowser,e.environmentOperatingSystem,e.environmentDeviceType,e.environmentScreenWidth,e.environmentScreenHeight,e.environmentDevicePixelRatio].every(e=>e==null))return{};try{return{environment:ie({browser:e.environmentBrowser,operatingSystem:e.environmentOperatingSystem,deviceType:e.environmentDeviceType,screenWidth:e.environmentScreenWidth,screenHeight:e.environmentScreenHeight,devicePixelRatio:e.environmentDevicePixelRatio},`${t} environment`)}}catch{return{}}}function oe(e){return{...e}}function _(e,t,n){let r=S(e,t);if(r<=0||r>n)throw E(`${t} is invalid`);return r}function se(e,t,n){let r=v(e,t,[`selector`,`tagName`,`textPreview`,`rect`,`source`,`componentStack`]),i=ve(r.componentStack,`${t} componentStack`);if(i.length>32)throw E(`${t} componentStack is too large`);if(!n&&(r.source!=null||i.length>0))throw E(`${t} exposes source metadata`);return{selector:x(r.selector,`${t} selector`,c),tagName:x(r.tagName,`${t} tagName`,128),textPreview:b(r.textPreview,`${t} textPreview`,l),rect:le(r.rect,`${t} rect`),source:n&&r.source!=null?ue(r.source,`${t} source`):null,componentStack:n?i.map((e,n)=>ue(e,`${t} stack[${n}]`)):[]}}function ce(e,t){let n=v(e,t,[`selector`,`offsetX`,`offsetY`,`viewportX`,`viewportY`]);return{selector:b(n.selector,`${t} selector`,c),offsetX:C(n.offsetX,`${t} offsetX`),offsetY:C(n.offsetY,`${t} offsetY`),viewportX:C(n.viewportX,`${t} viewportX`),viewportY:C(n.viewportY,`${t} viewportY`)}}function le(e,t){let n=v(e,t,[`pageX`,`pageY`,`width`,`height`,`viewportX`,`viewportY`,`viewportWidth`,`viewportHeight`]),r={pageX:S(n.pageX,`${t} pageX`),pageY:S(n.pageY,`${t} pageY`),width:S(n.width,`${t} width`),height:S(n.height,`${t} height`),viewportX:S(n.viewportX,`${t} viewportX`),viewportY:S(n.viewportY,`${t} viewportY`),viewportWidth:S(n.viewportWidth,`${t} viewportWidth`),viewportHeight:S(n.viewportHeight,`${t} viewportHeight`)};if(r.width<0||r.height<0||r.viewportWidth<0||r.viewportHeight<0)throw E(`${t} has a negative dimension`);return r}function ue(e,n){let r=v(e,n,[`filePath`,`lineNumber`,`columnNumber`,`componentName`,`origin`,`generated`],[`generated`]),i=r.origin;if(i!==`app`&&i!==`shared-ui`&&i!==`dependency`&&i!==`generated`&&i!==`unknown`)throw E(`${n} origin is invalid`);let a=x(r.filePath,`${n} filePath`,c);return{filePath:a,lineNumber:xe(r.lineNumber,`${n} lineNumber`),columnNumber:xe(r.columnNumber,`${n} columnNumber`),componentName:r.componentName==null?null:x(r.componentName,`${n} componentName`,512),origin:t(a)}}function de(e,t){let n=v(e,t,[`provider`,`build`,`resolvedAt`]),r=n.provider;if(r!==`react-grab`&&r!==`embedded`&&r!==`custom`)throw E(`${t} provider is invalid`);let i=v(n.build,`${t} build`,[`buildId`,`gitCommit`,`generatedAt`,`mode`],[`generatedAt`]),a=i.mode;if(a!==`development`&&a!==`preview`&&a!==`production`)throw E(`${t} build mode is invalid`);return{provider:r,build:{buildId:x(i.buildId,`${t} buildId`,512),gitCommit:i.gitCommit==null?null:x(i.gitCommit,`${t} gitCommit`,256),...i.generatedAt==null?{}:{generatedAt:w(i.generatedAt,`${t} generatedAt`)},mode:a},resolvedAt:w(n.resolvedAt,`${t} resolvedAt`)}}function fe(e){return{...e}}function pe(e){return e.replace(/\/+$/,``)||`/`}function me(e){return`${e.origin}${e.pathname}${e.search?`?${e.search}`:``}${e.hash?`#${e.hash}`:``}`}function he(e){return{...e}}function ge(e){return{...e}}function _e(e){return{...e,build:{...e.build}}}function v(e,t,n,r=[]){let i=y(e,t);if(Object.keys(i).some(e=>!n.includes(e)))throw E(`${t} contains unknown fields`);for(let e of n)if(!r.includes(e)&&!Object.hasOwn(i,e))throw E(`${t} is missing ${e}`);return i}function y(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw E(`${t} is missing or invalid`);return e}function ve(e,t){if(!Array.isArray(e))throw E(`${t} is missing or invalid`);return e}function b(e,t,n){if(typeof e!=`string`||ye(e,n)>n)throw E(`${t} is invalid or too long`);return e}function ye(e,t){let n=0;for(let r of e)if(n+=1,n>t)return n;return n}function x(e,t,n){let r=b(e,t,n);if(!r.trim())throw E(`${t} is empty`);return r}function S(e,t){if(typeof e!=`number`||!Number.isFinite(e))throw E(`${t} is invalid`);return e}function be(e,t,n,r){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<n||e>r)throw E(`${t} is invalid`);return e}function C(e,t){let n=S(e,t);if(n<0||n>1)throw E(`${t} is outside 0..1`);return n}function w(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw E(`${t} is invalid`);return e}function xe(e,t){if(e===null)return null;if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0)throw E(`${t} is invalid`);return e}function Se(e,t){let n;try{n=new URL(e)}catch(e){throw E(`${t} is invalid`,e)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw E(`${t} must use HTTP or HTTPS`)}function T(e,t,n){Ce(e,t,n)}function Ce(e,t,n){let r;try{r=JSON.stringify(e)}catch(e){throw E(`${n} cannot be serialized`,e)}if(r.length>t)throw E(`${n} is too large`);return r}function E(e,t){return new u(e,{cause:t instanceof Error?t:void 0})}new Uint8Array([107,167,184,17,157,173,17,209,128,180,0,192,79,212,48,200]);const we=n.schema({entities:{$files:n.entity({path:n.string().unique().indexed(),url:n.string()}),$users:n.entity({email:n.string().unique().indexed()}),projects:n.entity({name:n.string(),slug:n.string().unique().indexed(),allowedOrigin:n.string().optional(),originDisconnectedAt:n.number().optional(),originModelVersion:n.number().optional(),createdAt:n.number().indexed(),updatedAt:n.number()}),projectOrigins:n.entity({projectId:n.string().indexed(),originKey:n.string().unique().indexed(),origin:n.string().indexed(),label:n.string().optional(),createdAt:n.number().indexed(),updatedAt:n.number()}),reviewPages:n.entity({projectId:n.string().indexed(),autoRegistrationSlot:n.string().unique().indexed().optional(),name:n.string(),pathname:n.string(),stagingOrigin:n.string(),createdAt:n.number().indexed(),updatedAt:n.number()}),reviewPageBuilds:n.entity({projectId:n.string().indexed(),pageId:n.string().unique().indexed(),buildId:n.string(),gitCommit:n.string().optional(),generatedAt:n.number().optional(),mode:n.string(),updatedAt:n.number().indexed()}),reviewers:n.entity({authUserId:n.string().indexed(),projectId:n.string().indexed(),email:n.string().indexed(),displayName:n.string(),role:n.string(),createdAt:n.number()}),reviewerIdentityClaims:n.entity({reviewerId:n.string().unique().indexed(),projectId:n.string().indexed(),authUserId:n.string().indexed(),email:n.string(),displayName:n.string(),role:n.string(),createdAt:n.number()}),invitations:n.entity({projectId:n.string().indexed(),reviewerId:n.string().indexed().optional(),email:n.string().indexed(),status:n.string().indexed(),claimRevision:n.number(),claimedByAuthUserId:n.string().indexed().optional(),expiresAt:n.number().indexed(),createdAt:n.number(),acceptedAt:n.number().optional(),revokedAt:n.number().optional(),emailTokenHash:n.string().optional(),emailSentAt:n.number().optional(),reviewUrl:n.string().optional()}),comments:n.entity({pageId:n.string().indexed(),pageNumber:n.number().optional(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string().optional(),anchorSelector:n.string().optional(),anchorOffsetX:n.number().optional(),anchorOffsetY:n.number().optional(),anchorViewportX:n.number().optional(),anchorViewportY:n.number().optional(),targetKind:n.string().optional(),targetPageX:n.number().optional(),targetPageY:n.number().optional(),targetWidth:n.number().optional(),targetHeight:n.number().optional(),targetViewportX:n.number().optional(),targetViewportY:n.number().optional(),targetViewportWidth:n.number().optional(),targetViewportHeight:n.number().optional(),targetPageOrigin:n.string().optional(),targetPagePathname:n.string().optional(),targetPageSearch:n.string().optional(),targetPageHash:n.string().optional(),targetPageTitle:n.string().optional(),targetCapturedAt:n.number().optional(),environmentBrowser:n.string().optional(),environmentOperatingSystem:n.string().optional(),environmentDeviceType:n.string().optional(),environmentScreenWidth:n.number().optional(),environmentScreenHeight:n.number().optional(),environmentDevicePixelRatio:n.number().optional(),status:n.string().indexed(),workflowRevision:n.number(),createdAt:n.number().indexed(),updatedAt:n.number().indexed(),resolvedAt:n.number().optional(),resolvedById:n.string().optional(),deletingAt:n.number().optional()}),commentWorkflowClaims:n.entity({claimKey:n.string().unique().indexed(),commentId:n.string().indexed(),expectedWorkflowRevision:n.number(),createdAt:n.number().indexed()}),commentPageNumberClaims:n.entity({claimKey:n.string().unique().indexed(),pageId:n.string().indexed(),pageNumber:n.number(),commentId:n.string().indexed(),createdAt:n.number().indexed()}),commentTargetElements:n.entity({commentId:n.string().indexed(),slotKey:n.string().unique().indexed().optional(),ordinal:n.number(),selector:n.string(),tagName:n.string(),textPreview:n.string(),pageX:n.number(),pageY:n.number(),width:n.number(),height:n.number(),viewportX:n.number(),viewportY:n.number(),viewportWidth:n.number(),viewportHeight:n.number(),authorAuthUserId:n.string().indexed()}),commentScopeEntries:n.entity({commentId:n.string().indexed(),slotKey:n.string().unique().indexed().optional(),ordinal:n.number(),key:n.string(),valueType:n.string(),stringValue:n.string().optional(),numberValue:n.number().optional(),booleanValue:n.boolean().optional(),authorAuthUserId:n.string().indexed()}),commentSourceContexts:n.entity({commentId:n.string().unique().indexed(),pageId:n.string().indexed(),authorAuthUserId:n.string().indexed(),contextJson:n.string(),createdAt:n.number().indexed()}),replies:n.entity({pageId:n.string().indexed(),commentId:n.string().indexed(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string().optional(),createdAt:n.number().indexed(),updatedAt:n.number().indexed()}),reviewMessages:n.entity({pageId:n.string().indexed(),pathname:n.string().indexed(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string(),createdAt:n.number().indexed(),updatedAt:n.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`}},pageReviewMessages:{forward:{on:`reviewPages`,has:`many`,label:`reviewMessages`},reverse:{on:`reviewMessages`,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`}},reviewMessageAuthor:{forward:{on:`reviewMessages`,has:`one`,label:`author`},reverse:{on:`reviewers`,has:`many`,label:`reviewMessages`}}},rooms:{visualReview:{presence:n.entity({reviewerId:n.string(),displayName:n.string(),color:n.string(),active:n.boolean(),pathname:n.string().optional(),cursorX:n.number().optional(),cursorY:n.number().optional(),viewportWidth:n.number().optional(),viewportHeight:n.number().optional(),cursorChat:n.string().optional()})}}}),D={$default:`false`},O={$default:`false`},k=`$user.activeReviewInvitations`,A=`${k}.project.id`;function j(e){return[`auth.id != null`,`size(auth.ref('${k}.id')) > 0`,`size(auth.ref('${A}')) == size(auth.ref('${k}.id'))`,`size(auth.ref('${k}.status')) == size(auth.ref('${k}.id'))`,`size(auth.ref('${k}.expiresAt')) == size(auth.ref('${k}.id'))`,`size(auth.ref('${k}.revokedAt')) == 0`,`auth.ref('${k}.status').all(status, status == 'accepted')`,`auth.ref('${k}.expiresAt').all(expiresAt, request.time < timestamp(expiresAt))`,e].join(` && `)}function M(...e){return e.map(e=>`(${e})`).join(` && `)}function N(...e){return e.map(e=>`(${e})`).join(` || `)}function P(e){let t=`data.ref('${e}project.origins.origin')`,n=`data.ref('${e}project.allowedOrigin')`,r=`data.ref('${e}project.originModelVersion')`;return N(`request.origin in ${t}`,M(`size(${r}) == 0`,`request.origin in ${n}`))}j(`data.ref('project.id')[0] in auth.ref('${A}')`),N(`request.origin in data.ref('project.origins.origin')`,M(`size(data.ref('project.originModelVersion')) == 0`,`request.origin in data.ref('project.allowedOrigin')`)),N(`request.origin in data.ref('origins.origin')`,M(`size(data.ref('originModelVersion')) == 0`,`request.origin in data.ref('allowedOrigin')`)),j(`data.ref('page.project.id')[0] in auth.ref('${A}')`),P(`page.`),N(`auth.id != null && auth.id in data.ref('comment.page.project.owners.id')`,M(j(`data.ref('comment.page.project.id')[0] in auth.ref('${A}')`),P(`comment.page.`))),j(`data.ref('comment.page.project.id')[0] in auth.ref('${A}')`),P(`comment.page.`),j(`data.ref('page.project.id')[0] in auth.ref('${A}')`),P(`page.`),P(``);const Te=M(`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')`);M(`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`,Te),M(`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`,Te),M(`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')`),M(`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')`),M(`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')`),{...D},{...D},{...O},{...O},j(`data.id in auth.ref('${A}')`),{...D},{...O},{...D},{...D},{...O},{...D},{...O},j(`data.ref('project.id')[0] in auth.ref('${A}')`),{...D},{...O},{...D},{...D},{...O},{...O},{...D},{...O},{...D},{...D},{...D},{...D},{...D},{...D},{...D};function Ee(e){if(!e.trim())throw Error(`InstantDB app ID is required`);return r({appId:e,schema:we,devtool:!1})}var De=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(Oe(e,this.session.authUserId));return Ae(e,t.comments,t.replies)}async getProjectSnapshot(e){this.#t(e);let{data:t}=await this.db.queryOnce(ke(e,this.session.authUserId));return je(e,t.comments,t.replies)}subscribe(e,t,n){return this.db.subscribeQuery(Oe(e,this.session.authUserId),r=>{if(r.error){n?.(Re(r.error));return}if(r.data)try{t(Ae(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(ke(e,this.session.authUserId),r=>{if(r.error){n?.(Re(r.error));return}if(r.data)try{t(je(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 r=g(n.body).trim(),i=z(n.createdAt,`Comment createdAt`);if(z(n.updatedAt,`Comment updatedAt`)<i)throw new u(`Comment updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new u(`Comment edits must go through the review service`);if(n.status!==`open`||n.resolvedAt!==void 0||n.resolvedById!==void 0)throw new u(`New comments must start open`);let a=d(n.target);if(!Ie(n.anchor,a.publicTarget.anchor))throw new u(`Comment anchor does not match its target`);if(!this.#e)throw new u(`Comment creation requires the review service transport`);await this.#e.createComment({pageId:e,commentId:n.id,body:r,target:n.target,...n.scope===void 0?{}:{scope:n.scope}});return}case`comment.delete`:throw new u(`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=g(e.body,`Reply body`).trim(),r=z(e.createdAt,`Reply createdAt`);if(z(e.updatedAt,`Reply updatedAt`)<r)throw new u(`Reply updatedAt precedes createdAt`);if(e.createdAt!==e.updatedAt)throw new u(`Reply edits must go through the review service`);if(!this.#e)throw new u(`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 u(`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 Oe(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 ke(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 Ae(e,t,n){let r=t.map(t=>Ne(t,e));F(r,`comment`);let i=new Set(r.map(({id:e})=>e)),a=n.map(t=>Pe(t,e));F(a,`reply`);for(let e of a)if(!i.has(e.commentId))throw new u(`Reply ${e.id} references a comment outside the page snapshot`);return{pageId:e,comments:r,replies:a}}function je(e,t,n){let r=new Map,i=t.map(t=>{let n=L(t.pageId,`comment pageId`);Me(t.page,n,e,`comment ${String(t.id)}`);let i=I(t.page,`comment ${String(t.id)} page`),a=Ne(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});F(i,`comment`);let a=new Map(i.map(e=>[e.id,e])),o=n.map(t=>{let n=L(t.pageId,`reply pageId`),r=I(t.comment,`reply ${String(t.id)} comment`),i=L(t.commentId,`reply ${String(t.id)} commentId`);if(L(r.id,`reply ${String(t.id)} comment relation id`)!==i)throw new u(`Reply ${String(t.id)} has an inconsistent comment relation`);Me(r.page,n,e,`reply ${String(t.id)}`);let o=Pe(t,n),s=a.get(o.commentId);if(!s||s.pageId!==n)throw new u(`Reply ${o.id} references a comment outside the project snapshot`);return o});return F(o,`reply`),{projectId:e,pages:[...r.values()].sort((e,t)=>e.pathname.localeCompare(t.pathname)||e.id.localeCompare(t.id)),comments:i,replies:o}}function Me(e,t,n,r){let i=I(e,`${r} page`);if(L(i.id,`${r} page id`)!==t)throw new u(`${r} escaped its page relation`);if(L(I(i.project,`${r} project`).id,`${r} project id`)!==n)throw new u(`${r} escaped its project scope`)}function Ne(e,t){let n=I(e,`comment`),r=L(n.id,`comment id`);if(L(n.pageId,`comment ${r} pageId`)!==t)throw new u(`Comment ${r} escaped its page scope`);L(n.authorAuthUserId,`comment ${r} authorAuthUserId`);let i=!(Object.hasOwn(n,`anchor`)&&Object.hasOwn(n,`target`)),a=i?f(n,n.targetElements,`comment ${r} target`):te(n.target,`comment ${r} target`),o=i?{...a.anchor}:Fe(n.anchor,`comment ${r} anchor`);if(!Ie(o,a.anchor))throw new u(`Comment ${r} has inconsistent anchors`);let s=n.status;if(s!==`open`&&s!==`resolved`)throw new u(`Comment ${r} has an invalid status`);let c=z(n.createdAt,`comment ${r} createdAt`),l=z(n.updatedAt,`comment ${r} updatedAt`);if(l<c)throw new u(`Comment ${r} updatedAt precedes createdAt`);let d=He(n.resolvedAt,`comment ${r} resolvedAt`),m=Ue(n.resolvedById,`comment ${r} resolvedById`);if(s===`open`&&(d!==void 0||m!==void 0))throw new u(`Open comment ${r} contains resolution metadata`);if(s===`resolved`&&(d===void 0||m===void 0||d!==l))throw new u(`Resolved comment ${r} has invalid workflow metadata`);return{id:r,pageId:t,...We(n.pageNumber,`comment ${r} pageNumber`),authorId:L(n.authorId,`comment ${r} authorId`),authorName:L(n.authorName,`comment ${r} authorName`),body:g(n.body,`comment ${r} body`),anchor:o,target:a,...i?Le(p(n.scopeEntries)):n.scope==null?{}:{scope:ne(n.scope)},status:s,workflowRevision:Ve(n.workflowRevision,`comment ${r} workflowRevision`),createdAt:c,updatedAt:l,...d===void 0?{}:{resolvedAt:d},...m===void 0?{}:{resolvedById:m}}}function Pe(e,t){let n=I(e,`reply`),r=L(n.id,`reply id`);if(L(n.pageId,`reply ${r} pageId`)!==t)throw new u(`Reply ${r} escaped its page scope`);L(n.authorAuthUserId,`reply ${r} authorAuthUserId`);let i=z(n.createdAt,`reply ${r} createdAt`),a=z(n.updatedAt,`reply ${r} updatedAt`);if(a<i)throw new u(`Reply ${r} updatedAt precedes createdAt`);return{id:r,commentId:L(n.commentId,`reply ${r} commentId`),authorId:L(n.authorId,`reply ${r} authorId`),authorName:L(n.authorName,`reply ${r} authorName`),body:g(n.body,`reply ${r} body`),createdAt:i,updatedAt:a}}function Fe(e,t){let n=I(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 u(`${t} has invalid fields`);return{selector:Be(n.selector,`${t} selector`),offsetX:R(n.offsetX,`${t} offsetX`),offsetY:R(n.offsetY,`${t} offsetY`),viewportX:R(n.viewportX,`${t} viewportX`),viewportY:R(n.viewportY,`${t} viewportY`)}}function Ie(e,t){return e.selector===t.selector&&e.offsetX===t.offsetX&&e.offsetY===t.offsetY&&e.viewportX===t.viewportX&&e.viewportY===t.viewportY}function Le(e){return e===void 0?{}:{scope:e}}function F(e,t){let n=new Set;for(let r of e){if(n.has(r.id))throw new u(`Duplicate ${t} ${r.id}`);n.add(r.id)}}function Re(e){let t=ze(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 ze(e){return e instanceof Error?e.message:e&&typeof e==`object`&&`message`in e?String(e.message):``}function I(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new u(`${t} is missing or invalid`);return e}function Be(e,t){if(typeof e!=`string`)throw new u(`${t} is invalid`);return e}function L(e,t){let n=Be(e,t);if(!n.trim())throw new u(`${t} is empty`);return n}function R(e,t){if(typeof e!=`number`||!Number.isFinite(e)||e<0||e>1)throw new u(`${t} is invalid`);return e}function z(e,t){if(!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw new u(`${t} is invalid`);return e}function Ve(e,t){if(!Number.isSafeInteger(e)||e<0)throw new u(`${t} is invalid`);return e}function He(e,t){return e==null?void 0:z(e,t)}function Ue(e,t){return e==null?void 0:L(e,t)}function We(e,t){if(e==null)return{};let n=Ve(e,t);if(n<1)throw new u(`${t} is invalid`);return{pageNumber:n}}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`}),Object.freeze({comments:200,replies:1e3,sourceContexts:200});var Ge=class{db;session;roomCredential;#e=new Map;constructor(e,t,n){this.db=e,this.session=t,this.roomCredential=n}subscribe(e,t,n,r){let i=[],a=[],o=!1,s=[],c=()=>{o||n({pageId:e,peers:structuredClone(i),messages:structuredClone(a)})};if(t.cursors){let n=rt(e,t.roomId),a,l,u=this.roomCredential?.id===t.roomId?this.roomCredential:void 0,d=u??{id:t.roomId,expiresAt:2**53-1,refresh:async()=>void 0},f=t=>{let o=this.db.joinRoom(`visualReview`,t),s=o.subscribePresence({},e=>{if(e.error){r?.(at(e.error));return}i=Object.values(e.peers).map(e=>qe(e)).filter(e=>e!==null).sort((e,t)=>e.displayName.localeCompare(t.displayName)||e.peerId.localeCompare(t.peerId)),c()}),l=a;a=()=>{s(),o.leaveRoom()},this.#e.set(n,{pageId:e,roomId:t,publishPresence:e=>o.publishPresence(e)}),l?.()},p=()=>{if(!u||o)return;let e=Math.max(1e3,d.expiresAt-Date.now()+250);l=setTimeout(()=>{m()},e)},m=async()=>{try{let e=await d.refresh();if(o||!e)return;d={...e,refresh:d.refresh},u&&(u.id=e.id,u.expiresAt=e.expiresAt),f(e.id),p()}catch(e){if(o)return;r?.(at(e)),o||(l=setTimeout(()=>{m()},5e3))}};f(d.id),p(),s.push(()=>{l&&clearTimeout(l),this.#e.delete(n),a?.()})}return t.chat&&s.push(this.db.subscribeQuery(Ke(e,this.session.authUserId),t=>{if(t.error){r?.(at(t.error));return}if(t.data)try{a=t.data.reviewMessages.map(t=>Xe(t,e)).sort(it),c()}catch{r?.({type:`error`,code:`data-integrity`,recovery:`retry`,clearSnapshot:!0})}})),queueMicrotask(c),()=>{if(!o){o=!0;for(let e of s.reverse())try{e()}catch{}}}}publishPresence(e,t,n){let r=this.#e.get(rt(e,t));r&&r.publishPresence({reviewerId:this.session.reviewerId,displayName:this.session.displayName,color:n.color,active:n.active,pathname:Ye(n.pathname),...n.cursorX===void 0?{}:{cursorX:n.cursorX},...n.cursorY===void 0?{}:{cursorY:n.cursorY},...n.viewportWidth===void 0?{}:{viewportWidth:n.viewportWidth},...n.viewportHeight===void 0?{}:{viewportHeight:n.viewportHeight},cursorChat:Je(n.cursorChat)})}async sendMessage(e,t){throw Error(`Persisted review messages are no longer supported`)}};function Ke(e,t){return{reviewMessages:{$:{where:{pageId:e},order:{createdAt:`desc`},limit:200}},$users:{$:{where:{id:t}},activeReviewInvitations:{project:{}}}}}function qe(e){let t=$e(e.reviewerId,128),n=$e(e.displayName,512),r=typeof e.color==`string`&&/^#[0-9a-f]{6}$/iu.test(e.color)?e.color:null;if(!t||!n||!r||typeof e.active!=`boolean`)return null;let i=et(e.cursorX),a=et(e.cursorY),o=tt(e.viewportWidth),s=tt(e.viewportHeight),c=Je(e.cursorChat),l=Ye(e.pathname);return{peerId:e.peerId,reviewerId:t,displayName:n,color:r,active:e.active,pathname:l,...i===void 0?{}:{cursorX:i},...a===void 0?{}:{cursorY:a},...o===void 0?{}:{viewportWidth:o},...s===void 0?{}:{viewportHeight:s},...c?{cursorChat:c}:{}}}function Je(e){return typeof e==`string`?e.trim().slice(0,280):``}function Ye(e){if(typeof e!=`string`)return`/`;let t=e.trim();return t.startsWith(`/`)?t.slice(0,2e3):`/`}function Xe(e,t){let n=B(e.id,`Review message id`,128);if(B(e.pageId,`Review message pageId`,128)!==t)throw Error(`Review message page mismatch`);return{id:n,pageId:t,pathname:Qe(e.pathname),authorId:B(e.authorId,`Review message authorId`,128),authorName:B(e.authorName,`Review message authorName`,512),body:Ze(e.body),createdAt:nt(e.createdAt,`Review message createdAt`),updatedAt:nt(e.updatedAt,`Review message updatedAt`)}}function Ze(e){return B(e,`Review message body`,4e3)}function Qe(e){let t=B(e,`Review message pathname`,2e3);if(!t.startsWith(`/`))throw Error(`Review message pathname is invalid`);return t}function B(e,t,n){if(typeof e!=`string`)throw Error(`${t} is invalid`);let r=e.trim();if(!r||r.length>n)throw Error(`${t} is invalid`);return r}function $e(e,t){if(typeof e!=`string`)return null;let n=e.trim();return n&&n.length<=t?n:null}function et(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function tt(e){let t=et(e);return t!==void 0&&t>0?t:void 0}function nt(e,t){if(!Number.isSafeInteger(e)||e<0)throw Error(`${t} is invalid`);return e}function rt(e,t){return JSON.stringify([e,t])}function it(e,t){return e.createdAt-t.createdAt||e.id.localeCompare(t.id)}function at(e){let t=e&&typeof e==`object`&&`code`in e?String(e.code):``;if(/^INVITATION_(?:EXPIRED|NOT_FOUND|REQUIRED|REVOKED)$/u.test(t))return{type:`access-lost`,code:t===`INVITATION_EXPIRED`?`session-expired`:`membership-revoked`,recovery:`reauthenticate`,clearSnapshot:!0};let n=String(e instanceof Error||e&&typeof e==`object`&&`message`in e?e.message:e).toLowerCase();return n.includes(`expired`)||n.includes(`token`)?{type:`access-lost`,code:`session-expired`,recovery:`reauthenticate`,clearSnapshot:!0}:n.includes(`permission`)||n.includes(`forbidden`)||n.includes(`unauthorized`)?{type:`access-lost`,code:`permission-denied`,recovery:`reauthenticate`,clearSnapshot:!0}:{type:`error`,code:`transport`,recovery:`retry`,clearSnapshot:!0}}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`});var V=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewerCommentSaveError`}};function ot(e,t){let n=e.replace(/\/+$/,``),r=async(e,r)=>{let i=await t();if(!i)throw new V(`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 V(`NETWORK`,`리뷰 서버에 연결하지 못했습니다. 연결을 확인하고 다시 시도해 주세요.`)}if(!a.ok)throw new V(...await ct(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 V(`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:st(i.bytes)})}catch{throw new V(`NETWORK`,`리뷰 서버에 연결하지 못해 위치 캡처를 저장하지 못했습니다.`)}if(!o.ok)throw new V(...await ct(o))}}}function st(e){let t=new Uint8Array(e.byteLength);return t.set(e),t.buffer}async function ct(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]}}var H=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewBootstrapError`}};function lt(e,t={}){let n=e.trim();if(!n)throw Error(`InstantDB app ID is required`);return{async resolve(e){let{db:r,user:i}=await ut(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=ft(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 H(o.code,Dt(o.code));let s={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`},c=o.page.id,l=e.collaboration?.scopeId,u=(e.collaboration?.cursors===!0||e.collaboration?.chat===!0)&&t.resolveCollaborationRoom?await t.resolveCollaborationRoom({refreshToken:i.refresh_token,invitationId:e.invitationId,pageId:o.page.id,scopeId:e.collaboration.scopeId,signal:e.signal}):void 0,d=u&&t.resolveCollaborationRoom?{...u,refresh:async()=>{let n=await r.getAuth();if(!(!n?.refresh_token||l===void 0))return t.resolveCollaborationRoom?.({refreshToken:n.refresh_token,invitationId:e.invitationId,pageId:c,scopeId:l,signal:new AbortController().signal})}}:void 0,f=0;return{pageId:o.page.id,resolvePage:async n=>{let i=++f,a=()=>i!==f||n.signal.aborted,o=(e,t,n)=>({pageId:e,...n&&d?{collaborationRoomId:n.id}:{},commit:()=>{a()||(c=e,t!==void 0&&(l=t),!(!n||!d)&&(d.id=n.id,d.expiresAt=n.expiresAt))}});if(n.location.origin!==e.location.origin)throw new H(`PAGE_NOT_FOUND`,Dt(`PAGE_NOT_FOUND`));let{data:u}=await r.queryOnce({reviewPages:{$:{where:{projectId:s.projectId}}}});if(a())throw G();let p=Tt(n.location.pathname),m=pt(u.reviewPages,s.projectId,n.location.origin,p);if(!m&&t.resolveReviewPage){let i=await r.getAuth();if(a())throw G();if(!i?.refresh_token)throw Error(`리뷰 세션이 만료되어 페이지를 등록할 수 없습니다.`);if(await t.resolveReviewPage({refreshToken:i.refresh_token,invitationId:e.invitationId,origin:n.location.origin,pathname:p,signal:n.signal}),a()||({data:u}=await r.queryOnce({reviewPages:{$:{where:{projectId:s.projectId}}}}),a()))throw G();m=pt(u.reviewPages,s.projectId,n.location.origin,p)}if(!m)throw new H(`PAGE_NOT_FOUND`,Dt(`PAGE_NOT_FOUND`));if(n.collaboration?.cursors!==!0&&n.collaboration?.chat!==!0||d===void 0||t.resolveCollaborationRoom===void 0||!n.collaboration)return o(m.id,n.collaboration?.scopeId);let h=await r.getAuth();if(a())throw G();if(!h?.refresh_token)throw Error(`리뷰 세션이 만료되어 실시간 협업 연결을 갱신할 수 없습니다.`);let ee=await t.resolveCollaborationRoom({refreshToken:h.refresh_token,invitationId:e.invitationId,pageId:m.id,scopeId:n.collaboration.scopeId,signal:n.signal});if(a())throw G();return o(m.id,n.collaboration.scopeId,ee)},session:s,repository:new De(r,s,{...t.serviceUrl===void 0?{}:{commentTransport:ot(t.serviceUrl,async()=>(await r.getAuth())?.refresh_token??null)}}),...e.collaboration?.cursors===!0||e.collaboration?.chat===!0?{collaborationRepository:new Ge(r,s,d)}:{},...(e.collaboration?.cursors===!0||e.collaboration?.chat===!0)&&d?{collaborationRoomId:d.id}:{},allowedStagingHosts:[e.location.hostname]}}}}async function ut(e,t,n){let r=(n.databaseFactory??Ee)(e),i=!!t.emailToken,a;if(t.emailToken){if(!n.redeemEmailInvitation)throw new H(`INVITATION_EMAIL_REQUIRED`,`이 리뷰는 이메일 초대 링크에서만 시작할 수 있습니다.`);await _t(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 U(t.signal,()=>r.getAuth())&&await U(t.signal,async()=>r.auth.signOut()),await U(t.signal,async()=>r.auth.signInWithToken(e));let i=await U(t.signal,()=>r.getAuth());if(!i)throw Error(`인증 세션을 확인할 수 없습니다.`);a=i}else a=await mt(r,t.signal);if(!i)try{await dt(n.acceptInvitation,{refreshToken:a.refresh_token,invitationId:t.invitationId,suggestedDisplayName:St(a.email),authHost:t.authHost,signal:t.signal,styleNonce:t.styleNonce})}catch(e){throw Ct(e,`INVITATION_EMAIL_MISMATCH`)?new H(`INVITATION_EMAIL_REQUIRED`,`초대받은 이메일의 링크를 다시 열어 주세요.`):e}return{db:r,user:a}}async function dt(e,t){if(!e)return;let n={refreshToken:t.refreshToken,invitationId:t.invitationId,signal:t.signal};try{await e(n);return}catch(e){if(!Ct(e,`DISPLAY_NAME_REQUIRED`))throw e}let r=await gt(t.authHost,t.signal,t.suggestedDisplayName,t.styleNonce);await e({...n,displayName:r})}function ft(e,t,n,r){let i=e.find(({id:e})=>e===r.invitationId);if(!i||Et(i.email)!==Et(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=Tt(r.location.pathname),s=pt(n,i.projectId,r.location.origin,o);return s?{ok:!0,invitation:i,reviewer:a,page:s}:{ok:!1,code:`PAGE_NOT_FOUND`}}function pt(e,t,n,r){let i=e.filter(e=>e.projectId===t&&Tt(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 mt(e,t){let n=await U(t,()=>e.getAuth());if(n)return n;throw new H(`INVITATION_EMAIL_REQUIRED`,`초대받은 이메일의 링크를 열어 주세요.`)}async function U(e,t){ht(e);let n=await t();return ht(e),n}function ht(e){if(e.aborted)throw K()}function gt(e,t,n=``,r){if(t.aborted)return Promise.reject(K());let i=vt(e);i.replaceChildren(yt(i,r),bt(i));let a=i.querySelector(`form`),o=a.elements.namedItem(`displayName`),s=i.querySelector(`button`),c=i.querySelector(`.error`);return o.value=n.trim().slice(0,120),o.focus(),o.select(),new Promise((e,n)=>{let r=!1,l=e=>{r||(r=!0,t.removeEventListener(`abort`,u),i.removeEventListener(`keydown`,p),a.removeEventListener(`submit`,f),e())},u=()=>l(()=>n(K())),d=()=>{let t=o.value.trim();if(!t){c.textContent=`이름을 입력해 주세요.`,o.focus();return}if(t.length>120){c.textContent=`이름은 120자 이하여야 합니다.`,o.focus();return}c.textContent=``,s.disabled=!0,a.setAttribute(`aria-busy`,`true`),l(()=>e(t))},f=e=>{e.preventDefault(),d()},p=e=>{let t=e;if(t.key===`Escape`){t.preventDefault(),u();return}if(t.key===`Tab`){wt(i,t);return}t.key===`Enter`&&!t.isComposing&&t.target===o&&(t.preventDefault(),d())};t.addEventListener(`abort`,u,{once:!0}),i.addEventListener(`keydown`,p),a.addEventListener(`submit`,f)})}function _t(e,t,n){if(t.aborted)return Promise.reject(K());let r=vt(e);r.replaceChildren(yt(r,n),xt(r));let i=r.querySelector(`form`),a=r.querySelector(`button`);return a.focus(),new Promise((e,n)=>{let o=!1,s=e=>{o||(o=!0,t.removeEventListener(`abort`,c),r.removeEventListener(`keydown`,u),i.removeEventListener(`submit`,l),e())},c=()=>s(()=>n(K())),l=t=>{t.preventDefault(),a.disabled=!0,i.setAttribute(`aria-busy`,`true`),s(e)},u=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),c()):t.key===`Tab`&&wt(r,t)};t.addEventListener(`abort`,c,{once:!0}),r.addEventListener(`keydown`,u),i.addEventListener(`submit`,l)})}function vt(e){return e.shadowRoot??e.attachShadow({mode:`open`})}function yt(e,t){let n=e.ownerDocument.createElement(`style`);return t&&(n.nonce=t),n.textContent=Ot,n}function bt(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=W(t,`p`,`01.works`,`eyebrow`),i=W(t,`h2`,`표시 이름`);i.id=`visual-review-name-title`;let a=W(t,`p`,`피드백에 이 이름이 표시됩니다.`,`description`);a.id=`visual-review-name-description`;let o=W(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=W(t,`p`,``,`error`);c.setAttribute(`role`,`alert`);let l=W(t,`button`,`리뷰 시작`);return l.type=`submit`,n.append(r,i,a,o,s,c,l),n}function xt(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=W(t,`p`,`01.works`,`eyebrow`),i=W(t,`h2`,`리뷰 초대`);i.id=`visual-review-invitation-title`;let a=W(t,`p`,`초대받은 프로젝트를 열고 화면에 피드백을 남길 수 있습니다.`,`description`);a.id=`visual-review-invitation-description`;let o=W(t,`button`,`리뷰 시작`);return o.type=`submit`,n.append(r,i,a,o),n}function W(e,t,n,r){let i=e.createElement(t);return i.textContent=n,r&&(i.className=r),i}function St(e){return e?.split(`@`)[0]?.trim().slice(0,120)??``}function Ct(e,t){return!!(e&&typeof e==`object`&&`code`in e&&e.code===t)}function G(){return new DOMException(`Aborted`,`AbortError`)}function K(){return new H(`AUTH_CANCELLED`,`리뷰 로그인이 취소되었습니다.`)}function wt(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())}function Tt(e){return e.replace(/\/+$/,``)||`/`}function Et(e){return e.trim().toLowerCase()}function Dt(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`이 페이지는 아직 리뷰 대상이 아닙니다. 담당자에게 문의하세요.`}}const Ot=`
|
|
1
|
+
import{r as e}from"./install-Dh6WT91E.js";import{t}from"./embedded-source-DSDHbbeU.js";import{i as n,init as r}from"@instantdb/core";import{makeFunctionReference as i}from"convex/server";import{ConvexClient as a}from"convex/browser";const o=131072,s=32768,c=4096,l=1e3;var u=class extends Error{constructor(e,t){super(e,t),this.name=`InstantCaptureIntegrityError`}};function d(e){let t=re(e,`comment target`,!0),n={kind:t.kind,anchor:fe(t.anchor),region:he(t.region),elements:t.elements.map(e=>({selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,rect:he(e.rect),source:null,componentStack:[]})),pageUrl:t.pageUrl,pageTitle:t.pageTitle,capturedAt:t.capturedAt,...t.environment?{environment:oe(t.environment)}:{}},r={elements:t.elements.map(e=>({selector:e.selector,source:e.source?ge(e.source):null,componentStack:e.componentStack.map(ge)})),...t.sourceProvenance?{sourceProvenance:_e(t.sourceProvenance)}:{}};T(n,o,`Public target`);let i=Ce(r,65536,`Source context`);return{publicTarget:n,commentFields:m(n),targetElements:n.elements.map(h),sourceContextJson:i}}function f(e,t,n){let r=y(e,n),i={selector:b(r.anchorSelector,`${n} anchor selector`,c),offsetX:C(r.anchorOffsetX,`${n} anchor offsetX`),offsetY:C(r.anchorOffsetY,`${n} anchor offsetY`),viewportX:C(r.anchorViewportX,`${n} anchor viewportX`),viewportY:C(r.anchorViewportY,`${n} anchor viewportY`)},a=te({kind:r.targetKind,anchor:i,region:{pageX:r.targetPageX,pageY:r.targetPageY,width:r.targetWidth,height:r.targetHeight,viewportX:r.targetViewportX,viewportY:r.targetViewportY,viewportWidth:r.targetViewportWidth,viewportHeight:r.targetViewportHeight},elements:[],pageUrl:me({origin:x(r.targetPageOrigin,`${n} page origin`,1024),pathname:x(r.targetPagePathname,`${n} page pathname`,4096),search:b(r.targetPageSearch,`${n} page search`,1024),hash:b(r.targetPageHash,`${n} page hash`,1024)}),pageTitle:r.targetPageTitle,capturedAt:r.targetCapturedAt,...ae(r,n)},n),o=ee(t,`${n} elements`),s=a;for(let e of o)try{s=te({...a,elements:[...s.elements,e]},n)}catch{}return s}function p(e){if(!Array.isArray(e)||e.length===0)return;let t=[...e].map(e=>{try{let t=y(e,`Comment scope entry`);return{row:t,ordinal:be(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)),n={},r=new Set;for(let{row:e,ordinal:i}of t)if(!r.has(i)){r.add(i);try{let t=x(e.key,`Comment scope key`,256);if(Object.hasOwn(n,t))continue;switch(e.valueType){case`string`:n[t]=b(e.stringValue,`Comment scope ${t}`,l);break;case`number`:n[t]=S(e.numberValue,`Comment scope ${t}`);break;case`boolean`:if(typeof e.booleanValue!=`boolean`)throw E(`Comment scope ${t} is invalid`);n[t]=e.booleanValue;break;case`null`:n[t]=null;break;default:throw E(`Comment scope ${t} is invalid`)}}catch{}}if(Object.keys(n).length!==0)try{return T(n,s,`Comment scope`),n}catch{return}}function m(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:pe(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 h(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 ee(e,t){if(!Array.isArray(e)||e.length===0)return[];let n=[...e].map(e=>{try{let n=y(e,t);return{row:n,ordinal:be(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(se({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 te(e,t){return re(e,t,!1)}function g(e,t=`Comment body`){return x(e,t,2e4)}function ne(e){if(e==null)return;let t=y(e,`Comment scope`);if(Object.keys(t).length>20)throw E(`Comment scope has too many fields`);let n={};for(let[e,r]of Object.entries(t)){if(!e.trim()||e.length>256)throw E(`Comment scope has an invalid key`);if(typeof r==`string`){if(r.length>l)throw E(`Comment scope ${e} is too long`);n[e]=r}else if(typeof r==`number`)n[e]=S(r,`Comment scope ${e}`);else if(typeof r==`boolean`||r===null)n[e]=r;else throw E(`Comment scope ${e} is invalid`)}return T(n,s,`Comment scope`),n}function re(e,t,n){let r=v(e,t,[`kind`,`anchor`,`region`,`elements`,`pageUrl`,`pageTitle`,`capturedAt`,`environment`,`sourceProvenance`],[`environment`,`sourceProvenance`]),i=r.kind;if(i!==`element`&&i!==`region`&&i!==`viewport`)throw E(`${t} kind is invalid`);let a=ve(r.elements,`${t} elements`);if(a.length>8)throw E(`${t} contains too many elements`);if(!n&&r.sourceProvenance!=null)throw E(`${t} exposes source provenance`);let s=x(r.pageUrl,`${t} pageUrl`,8192);Se(s,`${t} pageUrl`);let c={kind:i,anchor:ce(r.anchor,`${t} anchor`),region:le(r.region,`${t} region`),elements:a.map((e,r)=>se(e,`${t} elements[${r}]`,n)),pageUrl:s,pageTitle:b(r.pageTitle,`${t} pageTitle`,l),capturedAt:w(r.capturedAt,`${t} capturedAt`),...r.environment==null?{}:{environment:ie(r.environment,`${t} environment`)},...n&&r.sourceProvenance!=null?{sourceProvenance:de(r.sourceProvenance,`${t} provenance`)}:{}};return T(c,n?196608:o,t),c}function ie(e,t){let n=v(e,t,[`browser`,`operatingSystem`,`deviceType`,`screenWidth`,`screenHeight`,`devicePixelRatio`]),r=n.deviceType;if(r!==`desktop`&&r!==`tablet`&&r!==`mobile`&&r!==`unknown`)throw E(`${t} deviceType is invalid`);return{browser:x(n.browser,`${t} browser`,120),operatingSystem:x(n.operatingSystem,`${t} operatingSystem`,120),deviceType:r,screenWidth:_(n.screenWidth,`${t} screenWidth`,1e5),screenHeight:_(n.screenHeight,`${t} screenHeight`,1e5),devicePixelRatio:_(n.devicePixelRatio,`${t} devicePixelRatio`,100)}}function ae(e,t){if([e.environmentBrowser,e.environmentOperatingSystem,e.environmentDeviceType,e.environmentScreenWidth,e.environmentScreenHeight,e.environmentDevicePixelRatio].every(e=>e==null))return{};try{return{environment:ie({browser:e.environmentBrowser,operatingSystem:e.environmentOperatingSystem,deviceType:e.environmentDeviceType,screenWidth:e.environmentScreenWidth,screenHeight:e.environmentScreenHeight,devicePixelRatio:e.environmentDevicePixelRatio},`${t} environment`)}}catch{return{}}}function oe(e){return{...e}}function _(e,t,n){let r=S(e,t);if(r<=0||r>n)throw E(`${t} is invalid`);return r}function se(e,t,n){let r=v(e,t,[`selector`,`tagName`,`textPreview`,`rect`,`source`,`componentStack`]),i=ve(r.componentStack,`${t} componentStack`);if(i.length>32)throw E(`${t} componentStack is too large`);if(!n&&(r.source!=null||i.length>0))throw E(`${t} exposes source metadata`);return{selector:x(r.selector,`${t} selector`,c),tagName:x(r.tagName,`${t} tagName`,128),textPreview:b(r.textPreview,`${t} textPreview`,l),rect:le(r.rect,`${t} rect`),source:n&&r.source!=null?ue(r.source,`${t} source`):null,componentStack:n?i.map((e,n)=>ue(e,`${t} stack[${n}]`)):[]}}function ce(e,t){let n=v(e,t,[`selector`,`offsetX`,`offsetY`,`viewportX`,`viewportY`]);return{selector:b(n.selector,`${t} selector`,c),offsetX:C(n.offsetX,`${t} offsetX`),offsetY:C(n.offsetY,`${t} offsetY`),viewportX:C(n.viewportX,`${t} viewportX`),viewportY:C(n.viewportY,`${t} viewportY`)}}function le(e,t){let n=v(e,t,[`pageX`,`pageY`,`width`,`height`,`viewportX`,`viewportY`,`viewportWidth`,`viewportHeight`]),r={pageX:S(n.pageX,`${t} pageX`),pageY:S(n.pageY,`${t} pageY`),width:S(n.width,`${t} width`),height:S(n.height,`${t} height`),viewportX:S(n.viewportX,`${t} viewportX`),viewportY:S(n.viewportY,`${t} viewportY`),viewportWidth:S(n.viewportWidth,`${t} viewportWidth`),viewportHeight:S(n.viewportHeight,`${t} viewportHeight`)};if(r.width<0||r.height<0||r.viewportWidth<0||r.viewportHeight<0)throw E(`${t} has a negative dimension`);return r}function ue(e,n){let r=v(e,n,[`filePath`,`lineNumber`,`columnNumber`,`componentName`,`origin`,`generated`],[`generated`]),i=r.origin;if(i!==`app`&&i!==`shared-ui`&&i!==`dependency`&&i!==`generated`&&i!==`unknown`)throw E(`${n} origin is invalid`);let a=x(r.filePath,`${n} filePath`,c);return{filePath:a,lineNumber:xe(r.lineNumber,`${n} lineNumber`),columnNumber:xe(r.columnNumber,`${n} columnNumber`),componentName:r.componentName==null?null:x(r.componentName,`${n} componentName`,512),origin:t(a)}}function de(e,t){let n=v(e,t,[`provider`,`build`,`resolvedAt`]),r=n.provider;if(r!==`react-grab`&&r!==`embedded`&&r!==`custom`)throw E(`${t} provider is invalid`);let i=v(n.build,`${t} build`,[`buildId`,`gitCommit`,`generatedAt`,`mode`],[`generatedAt`]),a=i.mode;if(a!==`development`&&a!==`preview`&&a!==`production`)throw E(`${t} build mode is invalid`);return{provider:r,build:{buildId:x(i.buildId,`${t} buildId`,512),gitCommit:i.gitCommit==null?null:x(i.gitCommit,`${t} gitCommit`,256),...i.generatedAt==null?{}:{generatedAt:w(i.generatedAt,`${t} generatedAt`)},mode:a},resolvedAt:w(n.resolvedAt,`${t} resolvedAt`)}}function fe(e){return{...e}}function pe(e){return e.replace(/\/+$/,``)||`/`}function me(e){return`${e.origin}${e.pathname}${e.search?`?${e.search}`:``}${e.hash?`#${e.hash}`:``}`}function he(e){return{...e}}function ge(e){return{...e}}function _e(e){return{...e,build:{...e.build}}}function v(e,t,n,r=[]){let i=y(e,t);if(Object.keys(i).some(e=>!n.includes(e)))throw E(`${t} contains unknown fields`);for(let e of n)if(!r.includes(e)&&!Object.hasOwn(i,e))throw E(`${t} is missing ${e}`);return i}function y(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw E(`${t} is missing or invalid`);return e}function ve(e,t){if(!Array.isArray(e))throw E(`${t} is missing or invalid`);return e}function b(e,t,n){if(typeof e!=`string`||ye(e,n)>n)throw E(`${t} is invalid or too long`);return e}function ye(e,t){let n=0;for(let r of e)if(n+=1,n>t)return n;return n}function x(e,t,n){let r=b(e,t,n);if(!r.trim())throw E(`${t} is empty`);return r}function S(e,t){if(typeof e!=`number`||!Number.isFinite(e))throw E(`${t} is invalid`);return e}function be(e,t,n,r){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<n||e>r)throw E(`${t} is invalid`);return e}function C(e,t){let n=S(e,t);if(n<0||n>1)throw E(`${t} is outside 0..1`);return n}function w(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw E(`${t} is invalid`);return e}function xe(e,t){if(e===null)return null;if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0)throw E(`${t} is invalid`);return e}function Se(e,t){let n;try{n=new URL(e)}catch(e){throw E(`${t} is invalid`,e)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw E(`${t} must use HTTP or HTTPS`)}function T(e,t,n){Ce(e,t,n)}function Ce(e,t,n){let r;try{r=JSON.stringify(e)}catch(e){throw E(`${n} cannot be serialized`,e)}if(r.length>t)throw E(`${n} is too large`);return r}function E(e,t){return new u(e,{cause:t instanceof Error?t:void 0})}new Uint8Array([107,167,184,17,157,173,17,209,128,180,0,192,79,212,48,200]);const we=n.schema({entities:{$files:n.entity({path:n.string().unique().indexed(),url:n.string()}),$users:n.entity({email:n.string().unique().indexed()}),projects:n.entity({name:n.string(),slug:n.string().unique().indexed(),allowedOrigin:n.string().optional(),originDisconnectedAt:n.number().optional(),originModelVersion:n.number().optional(),createdAt:n.number().indexed(),updatedAt:n.number()}),projectOrigins:n.entity({projectId:n.string().indexed(),originKey:n.string().unique().indexed(),origin:n.string().indexed(),label:n.string().optional(),createdAt:n.number().indexed(),updatedAt:n.number()}),reviewPages:n.entity({projectId:n.string().indexed(),autoRegistrationSlot:n.string().unique().indexed().optional(),name:n.string(),pathname:n.string(),stagingOrigin:n.string(),createdAt:n.number().indexed(),updatedAt:n.number()}),reviewPageBuilds:n.entity({projectId:n.string().indexed(),pageId:n.string().unique().indexed(),buildId:n.string(),gitCommit:n.string().optional(),generatedAt:n.number().optional(),mode:n.string(),updatedAt:n.number().indexed()}),reviewers:n.entity({authUserId:n.string().indexed(),projectId:n.string().indexed(),email:n.string().indexed(),displayName:n.string(),role:n.string(),createdAt:n.number()}),reviewerIdentityClaims:n.entity({reviewerId:n.string().unique().indexed(),projectId:n.string().indexed(),authUserId:n.string().indexed(),email:n.string(),displayName:n.string(),role:n.string(),createdAt:n.number()}),invitations:n.entity({projectId:n.string().indexed(),reviewerId:n.string().indexed().optional(),email:n.string().indexed(),status:n.string().indexed(),claimRevision:n.number(),claimedByAuthUserId:n.string().indexed().optional(),expiresAt:n.number().indexed(),createdAt:n.number(),acceptedAt:n.number().optional(),revokedAt:n.number().optional(),emailTokenHash:n.string().optional(),emailSentAt:n.number().optional(),reviewUrl:n.string().optional()}),comments:n.entity({pageId:n.string().indexed(),pageNumber:n.number().optional(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string().optional(),anchorSelector:n.string().optional(),anchorOffsetX:n.number().optional(),anchorOffsetY:n.number().optional(),anchorViewportX:n.number().optional(),anchorViewportY:n.number().optional(),targetKind:n.string().optional(),targetPageX:n.number().optional(),targetPageY:n.number().optional(),targetWidth:n.number().optional(),targetHeight:n.number().optional(),targetViewportX:n.number().optional(),targetViewportY:n.number().optional(),targetViewportWidth:n.number().optional(),targetViewportHeight:n.number().optional(),targetPageOrigin:n.string().optional(),targetPagePathname:n.string().optional(),targetPageSearch:n.string().optional(),targetPageHash:n.string().optional(),targetPageTitle:n.string().optional(),targetCapturedAt:n.number().optional(),environmentBrowser:n.string().optional(),environmentOperatingSystem:n.string().optional(),environmentDeviceType:n.string().optional(),environmentScreenWidth:n.number().optional(),environmentScreenHeight:n.number().optional(),environmentDevicePixelRatio:n.number().optional(),status:n.string().indexed(),workflowRevision:n.number(),createdAt:n.number().indexed(),updatedAt:n.number().indexed(),resolvedAt:n.number().optional(),resolvedById:n.string().optional(),deletingAt:n.number().optional()}),commentWorkflowClaims:n.entity({claimKey:n.string().unique().indexed(),commentId:n.string().indexed(),expectedWorkflowRevision:n.number(),createdAt:n.number().indexed()}),commentPageNumberClaims:n.entity({claimKey:n.string().unique().indexed(),pageId:n.string().indexed(),pageNumber:n.number(),commentId:n.string().indexed(),createdAt:n.number().indexed()}),commentTargetElements:n.entity({commentId:n.string().indexed(),slotKey:n.string().unique().indexed().optional(),ordinal:n.number(),selector:n.string(),tagName:n.string(),textPreview:n.string(),pageX:n.number(),pageY:n.number(),width:n.number(),height:n.number(),viewportX:n.number(),viewportY:n.number(),viewportWidth:n.number(),viewportHeight:n.number(),authorAuthUserId:n.string().indexed()}),commentScopeEntries:n.entity({commentId:n.string().indexed(),slotKey:n.string().unique().indexed().optional(),ordinal:n.number(),key:n.string(),valueType:n.string(),stringValue:n.string().optional(),numberValue:n.number().optional(),booleanValue:n.boolean().optional(),authorAuthUserId:n.string().indexed()}),commentSourceContexts:n.entity({commentId:n.string().unique().indexed(),pageId:n.string().indexed(),authorAuthUserId:n.string().indexed(),contextJson:n.string(),createdAt:n.number().indexed()}),replies:n.entity({pageId:n.string().indexed(),commentId:n.string().indexed(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string().optional(),createdAt:n.number().indexed(),updatedAt:n.number().indexed()}),reviewMessages:n.entity({pageId:n.string().indexed(),pathname:n.string().indexed(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string(),createdAt:n.number().indexed(),updatedAt:n.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`}},pageReviewMessages:{forward:{on:`reviewPages`,has:`many`,label:`reviewMessages`},reverse:{on:`reviewMessages`,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`}},reviewMessageAuthor:{forward:{on:`reviewMessages`,has:`one`,label:`author`},reverse:{on:`reviewers`,has:`many`,label:`reviewMessages`}}},rooms:{visualReview:{presence:n.entity({reviewerId:n.string(),displayName:n.string(),color:n.string(),active:n.boolean(),pathname:n.string().optional(),cursorX:n.number().optional(),cursorY:n.number().optional(),viewportWidth:n.number().optional(),viewportHeight:n.number().optional(),cursorChat:n.string().optional()})}}}),D={$default:`false`},O={$default:`false`},k=`$user.activeReviewInvitations`,A=`${k}.project.id`;function j(e){return[`auth.id != null`,`size(auth.ref('${k}.id')) > 0`,`size(auth.ref('${A}')) == size(auth.ref('${k}.id'))`,`size(auth.ref('${k}.status')) == size(auth.ref('${k}.id'))`,`size(auth.ref('${k}.expiresAt')) == size(auth.ref('${k}.id'))`,`size(auth.ref('${k}.revokedAt')) == 0`,`auth.ref('${k}.status').all(status, status == 'accepted')`,`auth.ref('${k}.expiresAt').all(expiresAt, request.time < timestamp(expiresAt))`,e].join(` && `)}function M(...e){return e.map(e=>`(${e})`).join(` && `)}function N(...e){return e.map(e=>`(${e})`).join(` || `)}function P(e){let t=`data.ref('${e}project.origins.origin')`,n=`data.ref('${e}project.allowedOrigin')`,r=`data.ref('${e}project.originModelVersion')`;return N(`request.origin in ${t}`,M(`size(${r}) == 0`,`request.origin in ${n}`))}j(`data.ref('project.id')[0] in auth.ref('${A}')`),N(`request.origin in data.ref('project.origins.origin')`,M(`size(data.ref('project.originModelVersion')) == 0`,`request.origin in data.ref('project.allowedOrigin')`)),N(`request.origin in data.ref('origins.origin')`,M(`size(data.ref('originModelVersion')) == 0`,`request.origin in data.ref('allowedOrigin')`)),j(`data.ref('page.project.id')[0] in auth.ref('${A}')`),P(`page.`),N(`auth.id != null && auth.id in data.ref('comment.page.project.owners.id')`,M(j(`data.ref('comment.page.project.id')[0] in auth.ref('${A}')`),P(`comment.page.`))),j(`data.ref('comment.page.project.id')[0] in auth.ref('${A}')`),P(`comment.page.`),j(`data.ref('page.project.id')[0] in auth.ref('${A}')`),P(`page.`),P(``);const Te=M(`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')`);M(`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`,Te),M(`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`,Te),M(`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')`),M(`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')`),M(`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')`),{...D},{...D},{...O},{...O},j(`data.id in auth.ref('${A}')`),{...D},{...O},{...D},{...D},{...O},{...D},{...O},j(`data.ref('project.id')[0] in auth.ref('${A}')`),{...D},{...O},{...D},{...D},{...O},{...O},{...D},{...O},{...D},{...D},{...D},{...D},{...D},{...D},{...D};function Ee(e){if(!e.trim())throw Error(`InstantDB app ID is required`);return r({appId:e,schema:we,devtool:!1})}var De=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(Oe(e,this.session.authUserId));return Ae(e,t.comments,t.replies)}async getProjectSnapshot(e){this.#t(e);let{data:t}=await this.db.queryOnce(ke(e,this.session.authUserId));return je(e,t.comments,t.replies)}subscribe(e,t,n){return this.db.subscribeQuery(Oe(e,this.session.authUserId),r=>{if(r.error){n?.(Re(r.error));return}if(r.data)try{t(Ae(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(ke(e,this.session.authUserId),r=>{if(r.error){n?.(Re(r.error));return}if(r.data)try{t(je(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 r=g(n.body).trim(),i=z(n.createdAt,`Comment createdAt`);if(z(n.updatedAt,`Comment updatedAt`)<i)throw new u(`Comment updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new u(`Comment edits must go through the review service`);if(n.status!==`open`||n.resolvedAt!==void 0||n.resolvedById!==void 0)throw new u(`New comments must start open`);let a=d(n.target);if(!Ie(n.anchor,a.publicTarget.anchor))throw new u(`Comment anchor does not match its target`);if(!this.#e)throw new u(`Comment creation requires the review service transport`);await this.#e.createComment({pageId:e,commentId:n.id,body:r,target:n.target,...n.scope===void 0?{}:{scope:n.scope}});return}case`comment.delete`:throw new u(`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=g(e.body,`Reply body`).trim(),r=z(e.createdAt,`Reply createdAt`);if(z(e.updatedAt,`Reply updatedAt`)<r)throw new u(`Reply updatedAt precedes createdAt`);if(e.createdAt!==e.updatedAt)throw new u(`Reply edits must go through the review service`);if(!this.#e)throw new u(`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 u(`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 Oe(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 ke(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 Ae(e,t,n){let r=t.map(t=>Ne(t,e));F(r,`comment`);let i=new Set(r.map(({id:e})=>e)),a=n.map(t=>Pe(t,e));F(a,`reply`);for(let e of a)if(!i.has(e.commentId))throw new u(`Reply ${e.id} references a comment outside the page snapshot`);return{pageId:e,comments:r,replies:a}}function je(e,t,n){let r=new Map,i=t.map(t=>{let n=L(t.pageId,`comment pageId`);Me(t.page,n,e,`comment ${String(t.id)}`);let i=I(t.page,`comment ${String(t.id)} page`),a=Ne(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});F(i,`comment`);let a=new Map(i.map(e=>[e.id,e])),o=n.map(t=>{let n=L(t.pageId,`reply pageId`),r=I(t.comment,`reply ${String(t.id)} comment`),i=L(t.commentId,`reply ${String(t.id)} commentId`);if(L(r.id,`reply ${String(t.id)} comment relation id`)!==i)throw new u(`Reply ${String(t.id)} has an inconsistent comment relation`);Me(r.page,n,e,`reply ${String(t.id)}`);let o=Pe(t,n),s=a.get(o.commentId);if(!s||s.pageId!==n)throw new u(`Reply ${o.id} references a comment outside the project snapshot`);return o});return F(o,`reply`),{projectId:e,pages:[...r.values()].sort((e,t)=>e.pathname.localeCompare(t.pathname)||e.id.localeCompare(t.id)),comments:i,replies:o}}function Me(e,t,n,r){let i=I(e,`${r} page`);if(L(i.id,`${r} page id`)!==t)throw new u(`${r} escaped its page relation`);if(L(I(i.project,`${r} project`).id,`${r} project id`)!==n)throw new u(`${r} escaped its project scope`)}function Ne(e,t){let n=I(e,`comment`),r=L(n.id,`comment id`);if(L(n.pageId,`comment ${r} pageId`)!==t)throw new u(`Comment ${r} escaped its page scope`);L(n.authorAuthUserId,`comment ${r} authorAuthUserId`);let i=!(Object.hasOwn(n,`anchor`)&&Object.hasOwn(n,`target`)),a=i?f(n,n.targetElements,`comment ${r} target`):te(n.target,`comment ${r} target`),o=i?{...a.anchor}:Fe(n.anchor,`comment ${r} anchor`);if(!Ie(o,a.anchor))throw new u(`Comment ${r} has inconsistent anchors`);let s=n.status;if(s!==`open`&&s!==`resolved`)throw new u(`Comment ${r} has an invalid status`);let c=z(n.createdAt,`comment ${r} createdAt`),l=z(n.updatedAt,`comment ${r} updatedAt`);if(l<c)throw new u(`Comment ${r} updatedAt precedes createdAt`);let d=He(n.resolvedAt,`comment ${r} resolvedAt`),m=Ue(n.resolvedById,`comment ${r} resolvedById`);if(s===`open`&&(d!==void 0||m!==void 0))throw new u(`Open comment ${r} contains resolution metadata`);if(s===`resolved`&&(d===void 0||m===void 0||d!==l))throw new u(`Resolved comment ${r} has invalid workflow metadata`);return{id:r,pageId:t,...We(n.pageNumber,`comment ${r} pageNumber`),authorId:L(n.authorId,`comment ${r} authorId`),authorName:L(n.authorName,`comment ${r} authorName`),body:g(n.body,`comment ${r} body`),anchor:o,target:a,...i?Le(p(n.scopeEntries)):n.scope==null?{}:{scope:ne(n.scope)},status:s,workflowRevision:Ve(n.workflowRevision,`comment ${r} workflowRevision`),createdAt:c,updatedAt:l,...d===void 0?{}:{resolvedAt:d},...m===void 0?{}:{resolvedById:m}}}function Pe(e,t){let n=I(e,`reply`),r=L(n.id,`reply id`);if(L(n.pageId,`reply ${r} pageId`)!==t)throw new u(`Reply ${r} escaped its page scope`);L(n.authorAuthUserId,`reply ${r} authorAuthUserId`);let i=z(n.createdAt,`reply ${r} createdAt`),a=z(n.updatedAt,`reply ${r} updatedAt`);if(a<i)throw new u(`Reply ${r} updatedAt precedes createdAt`);return{id:r,commentId:L(n.commentId,`reply ${r} commentId`),authorId:L(n.authorId,`reply ${r} authorId`),authorName:L(n.authorName,`reply ${r} authorName`),body:g(n.body,`reply ${r} body`),createdAt:i,updatedAt:a}}function Fe(e,t){let n=I(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 u(`${t} has invalid fields`);return{selector:Be(n.selector,`${t} selector`),offsetX:R(n.offsetX,`${t} offsetX`),offsetY:R(n.offsetY,`${t} offsetY`),viewportX:R(n.viewportX,`${t} viewportX`),viewportY:R(n.viewportY,`${t} viewportY`)}}function Ie(e,t){return e.selector===t.selector&&e.offsetX===t.offsetX&&e.offsetY===t.offsetY&&e.viewportX===t.viewportX&&e.viewportY===t.viewportY}function Le(e){return e===void 0?{}:{scope:e}}function F(e,t){let n=new Set;for(let r of e){if(n.has(r.id))throw new u(`Duplicate ${t} ${r.id}`);n.add(r.id)}}function Re(e){let t=ze(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 ze(e){return e instanceof Error?e.message:e&&typeof e==`object`&&`message`in e?String(e.message):``}function I(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new u(`${t} is missing or invalid`);return e}function Be(e,t){if(typeof e!=`string`)throw new u(`${t} is invalid`);return e}function L(e,t){let n=Be(e,t);if(!n.trim())throw new u(`${t} is empty`);return n}function R(e,t){if(typeof e!=`number`||!Number.isFinite(e)||e<0||e>1)throw new u(`${t} is invalid`);return e}function z(e,t){if(!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw new u(`${t} is invalid`);return e}function Ve(e,t){if(!Number.isSafeInteger(e)||e<0)throw new u(`${t} is invalid`);return e}function He(e,t){return e==null?void 0:z(e,t)}function Ue(e,t){return e==null?void 0:L(e,t)}function We(e,t){if(e==null)return{};let n=Ve(e,t);if(n<1)throw new u(`${t} is invalid`);return{pageNumber:n}}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`}),Object.freeze({comments:200,replies:1e3,sourceContexts:200});var Ge=class{db;session;roomCredential;#e=new Map;constructor(e,t,n){this.db=e,this.session=t,this.roomCredential=n}subscribe(e,t,n,r){let i=[],a=[],o=!1,s=[],c=()=>{o||n({pageId:e,peers:structuredClone(i),messages:structuredClone(a)})};if(t.cursors){let n=rt(e,t.roomId),a,l,u=this.roomCredential?.id===t.roomId?this.roomCredential:void 0,d=u??{id:t.roomId,expiresAt:2**53-1,refresh:async()=>void 0},f=t=>{let o=this.db.joinRoom(`visualReview`,t),s=o.subscribePresence({},e=>{if(e.error){r?.(at(e.error));return}i=Object.values(e.peers).map(e=>qe(e)).filter(e=>e!==null).sort((e,t)=>e.displayName.localeCompare(t.displayName)||e.peerId.localeCompare(t.peerId)),c()}),l=a;a=()=>{s(),o.leaveRoom()},this.#e.set(n,{pageId:e,roomId:t,publishPresence:e=>o.publishPresence(e)}),l?.()},p=()=>{if(!u||o)return;let e=Math.max(1e3,d.expiresAt-Date.now()+250);l=setTimeout(()=>{m()},e)},m=async()=>{try{let e=await d.refresh();if(o||!e)return;d={...e,refresh:d.refresh},u&&(u.id=e.id,u.expiresAt=e.expiresAt),f(e.id),p()}catch(e){if(o)return;r?.(at(e)),o||(l=setTimeout(()=>{m()},5e3))}};f(d.id),p(),s.push(()=>{l&&clearTimeout(l),this.#e.delete(n),a?.()})}return t.chat&&s.push(this.db.subscribeQuery(Ke(e,this.session.authUserId),t=>{if(t.error){r?.(at(t.error));return}if(t.data)try{a=t.data.reviewMessages.map(t=>Xe(t,e)).sort(it),c()}catch{r?.({type:`error`,code:`data-integrity`,recovery:`retry`,clearSnapshot:!0})}})),queueMicrotask(c),()=>{if(!o){o=!0;for(let e of s.reverse())try{e()}catch{}}}}publishPresence(e,t,n){let r=this.#e.get(rt(e,t));r&&r.publishPresence({reviewerId:this.session.reviewerId,displayName:this.session.displayName,color:n.color,active:n.active,pathname:Ye(n.pathname),...n.cursorX===void 0?{}:{cursorX:n.cursorX},...n.cursorY===void 0?{}:{cursorY:n.cursorY},...n.viewportWidth===void 0?{}:{viewportWidth:n.viewportWidth},...n.viewportHeight===void 0?{}:{viewportHeight:n.viewportHeight},cursorChat:Je(n.cursorChat)})}async sendMessage(e,t){throw Error(`Persisted review messages are no longer supported`)}};function Ke(e,t){return{reviewMessages:{$:{where:{pageId:e},order:{createdAt:`desc`},limit:200}},$users:{$:{where:{id:t}},activeReviewInvitations:{project:{}}}}}function qe(e){let t=$e(e.reviewerId,128),n=$e(e.displayName,512),r=typeof e.color==`string`&&/^#[0-9a-f]{6}$/iu.test(e.color)?e.color:null;if(!t||!n||!r||typeof e.active!=`boolean`)return null;let i=et(e.cursorX),a=et(e.cursorY),o=tt(e.viewportWidth),s=tt(e.viewportHeight),c=Je(e.cursorChat),l=Ye(e.pathname);return{peerId:e.peerId,reviewerId:t,displayName:n,color:r,active:e.active,pathname:l,...i===void 0?{}:{cursorX:i},...a===void 0?{}:{cursorY:a},...o===void 0?{}:{viewportWidth:o},...s===void 0?{}:{viewportHeight:s},...c?{cursorChat:c}:{}}}function Je(e){return typeof e==`string`?e.trim().slice(0,280):``}function Ye(e){if(typeof e!=`string`)return`/`;let t=e.trim();return t.startsWith(`/`)?t.slice(0,2e3):`/`}function Xe(e,t){let n=B(e.id,`Review message id`,128);if(B(e.pageId,`Review message pageId`,128)!==t)throw Error(`Review message page mismatch`);return{id:n,pageId:t,pathname:Qe(e.pathname),authorId:B(e.authorId,`Review message authorId`,128),authorName:B(e.authorName,`Review message authorName`,512),body:Ze(e.body),createdAt:nt(e.createdAt,`Review message createdAt`),updatedAt:nt(e.updatedAt,`Review message updatedAt`)}}function Ze(e){return B(e,`Review message body`,4e3)}function Qe(e){let t=B(e,`Review message pathname`,2e3);if(!t.startsWith(`/`))throw Error(`Review message pathname is invalid`);return t}function B(e,t,n){if(typeof e!=`string`)throw Error(`${t} is invalid`);let r=e.trim();if(!r||r.length>n)throw Error(`${t} is invalid`);return r}function $e(e,t){if(typeof e!=`string`)return null;let n=e.trim();return n&&n.length<=t?n:null}function et(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function tt(e){let t=et(e);return t!==void 0&&t>0?t:void 0}function nt(e,t){if(!Number.isSafeInteger(e)||e<0)throw Error(`${t} is invalid`);return e}function rt(e,t){return JSON.stringify([e,t])}function it(e,t){return e.createdAt-t.createdAt||e.id.localeCompare(t.id)}function at(e){let t=e&&typeof e==`object`&&`code`in e?String(e.code):``;if(/^INVITATION_(?:EXPIRED|NOT_FOUND|REQUIRED|REVOKED)$/u.test(t))return{type:`access-lost`,code:t===`INVITATION_EXPIRED`?`session-expired`:`membership-revoked`,recovery:`reauthenticate`,clearSnapshot:!0};let n=String(e instanceof Error||e&&typeof e==`object`&&`message`in e?e.message:e).toLowerCase();return n.includes(`expired`)||n.includes(`token`)?{type:`access-lost`,code:`session-expired`,recovery:`reauthenticate`,clearSnapshot:!0}:n.includes(`permission`)||n.includes(`forbidden`)||n.includes(`unauthorized`)?{type:`access-lost`,code:`permission-denied`,recovery:`reauthenticate`,clearSnapshot:!0}:{type:`error`,code:`transport`,recovery:`retry`,clearSnapshot:!0}}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`});var V=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewerCommentSaveError`}};function ot(e,t){let n=e.replace(/\/+$/,``),r=async(e,r)=>{let i=await t();if(!i)throw new V(`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 V(`NETWORK`,`리뷰 서버에 연결하지 못했습니다. 연결을 확인하고 다시 시도해 주세요.`)}if(!a.ok)throw new V(...await ct(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 V(`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:st(i.bytes)})}catch{throw new V(`NETWORK`,`리뷰 서버에 연결하지 못해 위치 캡처를 저장하지 못했습니다.`)}if(!o.ok)throw new V(...await ct(o))}}}function st(e){let t=new Uint8Array(e.byteLength);return t.set(e),t.buffer}async function ct(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]}}var H=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewBootstrapError`}};function lt(e,t={}){let n=e.trim();if(!n)throw Error(`InstantDB app ID is required`);return{async resolve(e){let{db:r,user:i}=await ut(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=ft(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 H(o.code,Ot(o.code));let s={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`},c=o.page.id,l=e.collaboration?.scopeId,u=(e.collaboration?.cursors===!0||e.collaboration?.chat===!0)&&t.resolveCollaborationRoom?await t.resolveCollaborationRoom({refreshToken:i.refresh_token,invitationId:e.invitationId,pageId:o.page.id,scopeId:e.collaboration.scopeId,signal:e.signal}):void 0,d=u&&t.resolveCollaborationRoom?{...u,refresh:async()=>{let n=await r.getAuth();if(!(!n?.refresh_token||l===void 0))return t.resolveCollaborationRoom?.({refreshToken:n.refresh_token,invitationId:e.invitationId,pageId:c,scopeId:l,signal:new AbortController().signal})}}:void 0,f=0;return{pageId:o.page.id,resolvePage:async n=>{let i=++f,a=()=>i!==f||n.signal.aborted,o=(e,t,n)=>({pageId:e,...n&&d?{collaborationRoomId:n.id}:{},commit:()=>{a()||(c=e,t!==void 0&&(l=t),!(!n||!d)&&(d.id=n.id,d.expiresAt=n.expiresAt))}});if(n.location.origin!==e.location.origin)throw new H(`PAGE_NOT_FOUND`,Ot(`PAGE_NOT_FOUND`));let{data:u}=await r.queryOnce({reviewPages:{$:{where:{projectId:s.projectId}}}});if(a())throw G();let p=Et(n.location.pathname),m=pt(u.reviewPages,s.projectId,n.location.origin,p);if(!m&&t.resolveReviewPage){let i=await r.getAuth();if(a())throw G();if(!i?.refresh_token)throw Error(`리뷰 세션이 만료되어 페이지를 등록할 수 없습니다.`);if(await t.resolveReviewPage({refreshToken:i.refresh_token,invitationId:e.invitationId,origin:n.location.origin,pathname:p,signal:n.signal}),a()||({data:u}=await r.queryOnce({reviewPages:{$:{where:{projectId:s.projectId}}}}),a()))throw G();m=pt(u.reviewPages,s.projectId,n.location.origin,p)}if(!m)throw new H(`PAGE_NOT_FOUND`,Ot(`PAGE_NOT_FOUND`));if(n.collaboration?.cursors!==!0&&n.collaboration?.chat!==!0||d===void 0||t.resolveCollaborationRoom===void 0||!n.collaboration)return o(m.id,n.collaboration?.scopeId);let h=await r.getAuth();if(a())throw G();if(!h?.refresh_token)throw Error(`리뷰 세션이 만료되어 실시간 협업 연결을 갱신할 수 없습니다.`);let ee=await t.resolveCollaborationRoom({refreshToken:h.refresh_token,invitationId:e.invitationId,pageId:m.id,scopeId:n.collaboration.scopeId,signal:n.signal});if(a())throw G();return o(m.id,n.collaboration.scopeId,ee)},session:s,repository:new De(r,s,{...t.serviceUrl===void 0?{}:{commentTransport:ot(t.serviceUrl,async()=>(await r.getAuth())?.refresh_token??null)}}),...e.collaboration?.cursors===!0||e.collaboration?.chat===!0?{collaborationRepository:new Ge(r,s,d)}:{},...(e.collaboration?.cursors===!0||e.collaboration?.chat===!0)&&d?{collaborationRoomId:d.id}:{},allowedStagingHosts:[e.location.hostname],sessionScope:`browser`}}}}async function ut(e,t,n){let r=(n.databaseFactory??Ee)(e),i=!!t.emailToken,a;if(t.emailToken){if(!n.redeemEmailInvitation)throw new H(`INVITATION_EMAIL_REQUIRED`,`이 리뷰는 이메일 초대 링크에서만 시작할 수 있습니다.`);await _t(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 U(t.signal,()=>r.getAuth())&&await U(t.signal,async()=>r.auth.signOut()),await U(t.signal,async()=>r.auth.signInWithToken(e));let i=await U(t.signal,()=>r.getAuth());if(!i)throw Error(`인증 세션을 확인할 수 없습니다.`);a=i}else a=await mt(r,t.signal);if(!i)try{await dt(n.acceptInvitation,{refreshToken:a.refresh_token,invitationId:t.invitationId,suggestedDisplayName:Ct(a.email),authHost:t.authHost,signal:t.signal,styleNonce:t.styleNonce})}catch(e){throw wt(e,`INVITATION_EMAIL_MISMATCH`)?new H(`INVITATION_EMAIL_REQUIRED`,`초대받은 이메일의 링크를 다시 열어 주세요.`):e}return{db:r,user:a}}async function dt(e,t){if(!e)return;let n={refreshToken:t.refreshToken,invitationId:t.invitationId,signal:t.signal};try{await e(n);return}catch(e){if(!wt(e,`DISPLAY_NAME_REQUIRED`))throw e}let r=await gt(t.authHost,t.signal,t.suggestedDisplayName,t.styleNonce);await e({...n,displayName:r})}function ft(e,t,n,r){let i=e.find(({id:e})=>e===r.invitationId);if(!i||Dt(i.email)!==Dt(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=Et(r.location.pathname),s=pt(n,i.projectId,r.location.origin,o);return s?{ok:!0,invitation:i,reviewer:a,page:s}:{ok:!1,code:`PAGE_NOT_FOUND`}}function pt(e,t,n,r){let i=e.filter(e=>e.projectId===t&&Et(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 mt(e,t){let n=await U(t,()=>e.getAuth());if(n)return n;throw new H(`INVITATION_EMAIL_REQUIRED`,`초대받은 이메일의 링크를 열어 주세요.`)}async function U(e,t){ht(e);let n=await t();return ht(e),n}function ht(e){if(e.aborted)throw K()}function gt(e,t,n=``,r){if(t.aborted)return Promise.reject(K());let i=yt(e);i.replaceChildren(bt(i,r),xt(i));let a=i.querySelector(`form`),o=a.elements.namedItem(`displayName`),s=i.querySelector(`button`),c=i.querySelector(`.error`);return o.value=n.trim().slice(0,120),o.focus(),o.select(),new Promise((e,n)=>{let r=!1,l=e=>{r||(r=!0,t.removeEventListener(`abort`,u),i.removeEventListener(`keydown`,p),a.removeEventListener(`submit`,f),e())},u=()=>l(()=>n(K())),d=()=>{let t=o.value.trim();if(!t){c.textContent=`이름을 입력해 주세요.`,o.focus();return}if(t.length>120){c.textContent=`이름은 120자 이하여야 합니다.`,o.focus();return}c.textContent=``,s.disabled=!0,a.setAttribute(`aria-busy`,`true`),l(()=>e(t))},f=e=>{e.preventDefault(),d()},p=e=>{let t=e;if(t.key===`Escape`){t.preventDefault(),u();return}if(t.key===`Tab`){Tt(i,t);return}t.key===`Enter`&&!t.isComposing&&t.target===o&&(t.preventDefault(),d())};t.addEventListener(`abort`,u,{once:!0}),i.addEventListener(`keydown`,p),a.addEventListener(`submit`,f)})}function _t(e,t,n){if(t.aborted)return Promise.reject(K());let r=yt(e);r.replaceChildren(bt(r,n),St(r));let i=r.querySelector(`form`),a=r.querySelector(`button`);return a.focus(),new Promise((e,n)=>{let o=!1,s=e=>{o||(o=!0,t.removeEventListener(`abort`,c),r.removeEventListener(`keydown`,u),i.removeEventListener(`submit`,l),e())},c=()=>s(()=>n(K())),l=t=>{t.preventDefault(),a.disabled=!0,i.setAttribute(`aria-busy`,`true`),s(e)},u=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),c()):t.key===`Tab`&&Tt(r,t)};t.addEventListener(`abort`,c,{once:!0}),r.addEventListener(`keydown`,u),i.addEventListener(`submit`,l)})}async function vt(e,t,n,r){if(t.aborted)throw K();let i=await n.requestCode();if(t.aborted)throw K();let a=yt(e),o=a.ownerDocument.createElement(`form`);o.setAttribute(`role`,`dialog`),o.setAttribute(`aria-modal`,`true`);let s=W(a.ownerDocument,`p`,`01.works`,`eyebrow`),c=W(a.ownerDocument,`h2`,`리뷰 접속 복구`),l=W(a.ownerDocument,`p`,`${i.emailHint}로 보낸 6자리 코드를 입력하세요.`,`description`),u=W(a.ownerDocument,`label`,`복구 코드`),d=a.ownerDocument.createElement(`input`);d.name=`code`,d.inputMode=`numeric`,d.autocomplete=`one-time-code`,d.pattern=`[0-9]{6}`,d.maxLength=6,d.required=!0;let f=W(a.ownerDocument,`p`,``,`error`);f.setAttribute(`role`,`alert`);let p=W(a.ownerDocument,`button`,`접속 복구`);return p.type=`submit`,u.append(d),o.append(s,c,l,u,f,p),a.replaceChildren(bt(a,r),o),d.focus(),new Promise((e,r)=>{let s=!1,c=e=>{s||(s=!0,t.removeEventListener(`abort`,l),a.removeEventListener(`keydown`,u),o.removeEventListener(`submit`,m),e())},l=()=>c(()=>r(K())),u=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),l()):t.key===`Tab`&&Tt(a,t)},m=t=>{t.preventDefault();let r=d.value.trim();if(!/^\d{6}$/.test(r)){f.textContent=`6자리 숫자를 입력해 주세요.`;return}p.disabled=!0,o.setAttribute(`aria-busy`,`true`),f.textContent=``,n.verifyCode(i.challengeId,r).then(t=>c(()=>e(t)),e=>{p.disabled=!1,o.removeAttribute(`aria-busy`),f.textContent=e instanceof Error?e.message:`복구 코드를 확인하지 못했습니다.`,d.select()})};t.addEventListener(`abort`,l,{once:!0}),a.addEventListener(`keydown`,u),o.addEventListener(`submit`,m)})}function yt(e){return e.shadowRoot??e.attachShadow({mode:`open`})}function bt(e,t){let n=e.ownerDocument.createElement(`style`);return t&&(n.nonce=t),n.textContent=kt,n}function xt(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=W(t,`p`,`01.works`,`eyebrow`),i=W(t,`h2`,`표시 이름`);i.id=`visual-review-name-title`;let a=W(t,`p`,`피드백에 이 이름이 표시됩니다.`,`description`);a.id=`visual-review-name-description`;let o=W(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=W(t,`p`,``,`error`);c.setAttribute(`role`,`alert`);let l=W(t,`button`,`리뷰 시작`);return l.type=`submit`,n.append(r,i,a,o,s,c,l),n}function St(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=W(t,`p`,`01.works`,`eyebrow`),i=W(t,`h2`,`리뷰 초대`);i.id=`visual-review-invitation-title`;let a=W(t,`p`,`초대받은 프로젝트를 열고 화면에 피드백을 남길 수 있습니다.`,`description`);a.id=`visual-review-invitation-description`;let o=W(t,`button`,`리뷰 시작`);return o.type=`submit`,n.append(r,i,a,o),n}function W(e,t,n,r){let i=e.createElement(t);return i.textContent=n,r&&(i.className=r),i}function Ct(e){return e?.split(`@`)[0]?.trim().slice(0,120)??``}function wt(e,t){return!!(e&&typeof e==`object`&&`code`in e&&e.code===t)}function G(){return new DOMException(`Aborted`,`AbortError`)}function K(){return new H(`AUTH_CANCELLED`,`리뷰 로그인이 취소되었습니다.`)}function Tt(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())}function Et(e){return e.replace(/\/+$/,``)||`/`}function Dt(e){return e.trim().toLowerCase()}function Ot(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`이 페이지는 아직 리뷰 대상이 아닙니다. 담당자에게 문의하세요.`}}const kt=`
|
|
2
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
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
4
|
.eyebrow{margin:0 0 10px;color:var(--vr-muted);font-size:10px;font-weight:700;letter-spacing:.09em;text-transform:uppercase}
|
|
@@ -10,4 +10,4 @@ import{r as e}from"./install-DSA2Fpbw.js";import{t}from"./embedded-source-DSDHbb
|
|
|
10
10
|
@media (pointer:coarse){input,button{height:44px}}
|
|
11
11
|
@media (max-width:480px){form{padding:18px}input{font-size:16px}}
|
|
12
12
|
@media (prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;transition:none!important;animation:none!important}}
|
|
13
|
-
`,q=Object.freeze({resolveSession:i(`reviews:resolveSession`),pageSnapshot:i(`reviews:pageSnapshot`),projectSnapshot:i(`reviews:projectSnapshot`),createComment:i(`reviews:createComment`),createReply:i(`reviews:createReply`),presenceList:i(`presence:list`),presenceUpdate:i(`presence:update`),presenceDisconnect:i(`presence:disconnect`),screenshotUploadUrl:i(`screenshots:generateUploadUrl`),screenshotCommit:i(`screenshots:commitUpload`),screenshotDiscard:i(`screenshots:discardUpload`)});Object.freeze({catalog:i(`owners:catalog`),listProjects:i(`owners:listProjects`),projectOverview:i(`owners:projectOverview`),createProject:i(`owners:createProject`),deleteProject:i(`owners:deleteProject`),addOrigin:i(`owners:addOrigin`),removeOrigin:i(`owners:removeOrigin`),createPage:i(`owners:createPage`),deletePage:i(`owners:deletePage`),upsertPageBuild:i(`owners:upsertPageBuild`),createInvitation:i(`owners:createInvitation`),revokeInvitation:i(`owners:revokeInvitation`),setCommentStatus:i(`owners:setCommentStatus`),createReply:i(`owners:createReply`),deleteComment:i(`owners:deleteComment`),deleteReply:i(`owners:deleteReply`),screenshotDownload:i(`screenshots:ownerDownload`)});var kt=class{client;session;#e;#t;#n;constructor(e,t,n){this.client=e,this.session=t,this.#e=Y(n.invitationId??t.invitationId,`invitationId`),this.#t=Nt(n.origin),this.#n=n.fetch??globalThis.fetch.bind(globalThis)}async attachScreenshot(e,t,n){Y(e,`pageId`);let r=Y(t,`commentId`);if(n.bytes.byteLength===0||n.bytes.byteLength>15e5)throw Error(`Screenshot size is invalid`);let i=await this.client.mutation(q.screenshotUploadUrl,{...this.#r(),commentId:r}),a=await this.#n(i,{method:`POST`,headers:{"content-type":n.contentType},body:At(n.bytes)});if(!a.ok)throw Error(`Screenshot upload failed`);let o=await a.json();if(typeof o.storageId!=`string`||!o.storageId)throw Error(`Screenshot upload returned an invalid storage ID`);try{await this.client.mutation(q.screenshotCommit,{...this.#r(),commentId:r,storageId:o.storageId,contentType:n.contentType,width:n.width,height:n.height})}catch(e){throw await this.client.mutation(q.screenshotDiscard,{...this.#r(),commentId:r,storageId:o.storageId}).catch(()=>void 0),e}}async getSnapshot(e){return Mt(await this.client.query(q.pageSnapshot,{...this.#r(),pageId:Y(e,`pageId`)}))}async getProjectSnapshot(e){return this.#i(e),structuredClone(await this.client.query(q.projectSnapshot,{...this.#r(),projectId:e}))}subscribe(e,t,n){return this.client.onUpdate(q.pageSnapshot,{...this.#r(),pageId:Y(e,`pageId`)},e=>t(Mt(e)),e=>n?.(J(e)))}subscribeProject(e,t,n){return this.#i(e),this.client.onUpdate(q.projectSnapshot,{...this.#r(),projectId:e},e=>t(structuredClone(e)),e=>n?.(J(e)))}async mutate(e,t){switch(t.type){case`comment.upsert`:{let n=t.comment;if(n.pageId!==e)throw Error(`Comment page mismatch`);if(n.authorId!==this.session.reviewerId)throw Error(`Comment author mismatch`);if(n.status!==`open`||n.resolvedAt!==void 0||n.resolvedById!==void 0||n.createdAt!==n.updatedAt)throw Error(`Only new open comments can be created by a reviewer`);let r=g(n.body).trim(),i=d(n.target),a=n.scope===void 0?void 0:ne(n.scope);await this.client.mutation(q.createComment,{...this.#r(),pageId:e,commentId:n.id,body:r,targetJson:JSON.stringify(i.publicTarget),sourceContextJson:i.sourceContextJson,...a===void 0?{}:{scopeJson:JSON.stringify(a)}});return}case`reply.upsert`:{let e=t.reply;if(e.authorId!==this.session.reviewerId)throw Error(`Reply author mismatch`);if(e.createdAt!==e.updatedAt)throw Error(`Reply edits require an owner command`);await this.client.mutation(q.createReply,{...this.#r(),commentId:e.commentId,replyId:e.id,body:g(e.body,`Reply body`).trim()});return}case`comment.delete`:throw Error(`Comment deletion requires an owner command`);case`reply.delete`:throw Error(`Reply deletion requires an owner command`)}}#r(){return{invitationId:this.#e,origin:this.#t}}#i(e){if(!e.trim()||e!==this.session.projectId)throw Error(`Project does not belong to the reviewer session`)}};function At(e){let t=new Uint8Array(e.byteLength);return t.set(e),t.buffer}function J(e){let t=jt(e);return t===`UNAUTHENTICATED`||t===`INVITATION_EXPIRED`?{type:`access-lost`,code:`session-expired`,recovery:`reauthenticate`,clearSnapshot:!0}:t===`INVITATION_REVOKED`||t===`MEMBERSHIP_REVOKED`?{type:`access-lost`,code:`membership-revoked`,recovery:`reauthenticate`,clearSnapshot:!0}:t===`ORIGIN_MISMATCH`||t===`ORIGIN_NOT_ALLOWED`||t===`INVITATION_REQUIRED`?{type:`access-lost`,code:`permission-denied`,recovery:`reauthenticate`,clearSnapshot:!0}:{type:`error`,code:e instanceof Error?`transport`:`unknown`,recovery:`retry`,clearSnapshot:!0}}function jt(e){if(!e||typeof e!=`object`)return;let t=e.data;if(typeof t==`string`)return t;if(t&&typeof t==`object`){let e=t.code;if(typeof e==`string`)return e}}function Mt(e){return structuredClone(e)}function Y(e,t){let n=e.trim();if(!n)throw Error(`${t} is required`);return n}function Nt(e){let t=Y(e,`origin`);try{let e=new URL(t);if(e.origin!==t)throw Error();return e.origin}catch{throw Error(`A valid browser origin is required`)}}var Pt=class{client;session;#e=new Map;#t;#n;#r;#i;#a;#o;constructor(e,t,n){this.client=e,this.session=t,this.#t=(n.invitationId??t.invitationId).trim(),this.#n=new URL(n.origin).origin,this.#r=Ft(n.cursorThrottleMs??80,40,1e3),this.#i=Ft(n.heartbeatMs??1e4,2e3,2e4),this.#a=n.now??Date.now,this.#o=n.sessionId??(()=>globalThis.crypto.randomUUID())}subscribe(e,t,n,r){let i=!1,a=[],o=this.#s(e,t.roomId),s=()=>{i||n({pageId:e,peers:structuredClone(a),messages:[]})},c=t.cursors||t.chat?this.client.onUpdate(q.presenceList,{...this.#d(),pageId:e,roomId:t.roomId},e=>{let t=this.#a();a=e.filter(({peerId:e,expiresAt:n})=>e!==o.sessionId&&n>t).map(({expiresAt:e,...t})=>t).sort((e,t)=>e.displayName.localeCompare(t.displayName)||e.peerId.localeCompare(t.peerId)),s()},e=>r?.(J(e))):()=>void 0;return queueMicrotask(s),()=>{i||(i=!0,c(),this.#u(o))}}publishPresence(e,t,n){let r=this.#e.get(X(e,t));!r||r.stopped||(r.latest={...n,reviewerId:this.session.reviewerId,displayName:this.session.displayName},this.#c(r))}async sendMessage(e,t){let n=[...this.#e.values()].find(t=>t.pageId===e);n?.latest&&(n.latest={...n.latest,cursorChat:t.body.slice(0,4e3)},await this.#l(n))}#s(e,t){let n=X(e,t),r=this.#e.get(n);r&&this.#u(r);let i={pageId:e,roomId:t,sessionId:this.#o(),stopped:!1,lastSentAt:-1/0,inFlight:!1};return i.heartbeatTimer=setInterval(()=>{i.latest&&this.#l(i)},this.#i),this.#e.set(n,i),i}#c(e){if(e.inFlight||e.flushTimer||e.stopped)return;let t=Math.max(0,this.#r-(this.#a()-e.lastSentAt));if(t===0){this.#l(e);return}e.flushTimer=setTimeout(()=>{e.flushTimer=void 0,this.#l(e)},t)}async#l(e){if(e.stopped||e.inFlight||!e.latest)return;e.inFlight=!0;let t=e.latest;e.latest=void 0;try{await this.client.mutation(q.presenceUpdate,{...this.#d(),pageId:e.pageId,roomId:e.roomId,sessionId:e.sessionId,color:t.color,active:t.active,...t.pathname===void 0?{}:{pathname:t.pathname},...t.cursorX===void 0?{}:{cursorX:t.cursorX},...t.cursorY===void 0?{}:{cursorY:t.cursorY},...t.viewportWidth===void 0?{}:{viewportWidth:t.viewportWidth},...t.viewportHeight===void 0?{}:{viewportHeight:t.viewportHeight},...t.cursorChat===void 0?{}:{cursorChat:t.cursorChat}}),e.lastSentAt=this.#a()}finally{e.inFlight=!1,e.latest&&this.#c(e)}}#u(e){e.stopped||(e.stopped=!0,e.flushTimer&&clearTimeout(e.flushTimer),e.heartbeatTimer&&clearInterval(e.heartbeatTimer),this.#e.delete(X(e.pageId,e.roomId)),this.client.mutation(q.presenceDisconnect,{...this.#d(),sessionId:e.sessionId}).catch(()=>void 0))}#d(){return{invitationId:this.#t,origin:this.#n}}};function X(e,t){return`${e}\u0000${t}`}function Ft(e,t,n){return Number.isFinite(e)?Math.min(n,Math.max(t,Math.round(e))):t}function It(e,t){let n=e.trim();if(!/^https:\/\/[^/]+$/.test(n))throw Error(`A valid HTTPS Convex deployment URL is required`);let r=new a(n);return r.setAuth(t),r}function Lt(e,t){let n=e.trim();if(!n)throw Error(`Convex deployment URL is required`);return{async resolve(e){let r=await t.fetchAccessToken(zt(e,!1));if(!r)throw Error(`Convex review authentication is required`);let i=r,a=(t.clientFactory??It)(n,async({forceRefreshToken:n})=>{if(!n&&i){let e=i;return i=null,e}return t.fetchAccessToken({...zt(e,n),signal:new AbortController().signal})}),o=await a.mutation(q.resolveSession,{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname}),s=Vt(o.session,e.invitationId),c=o.pageId,l=e.collaboration?await Bt(t,e,c,e.collaboration.scopeId):void 0,u=0;return Rt({client:a,session:s,request:e,pageId:c,roomId:l,resolvePage:async n=>{if(n.location.origin!==e.location.origin)throw Error(`Convex review session cannot move to another origin`);let r=++u,i=await a.mutation(q.resolveSession,{invitationId:e.invitationId,origin:n.location.origin,pathname:n.location.pathname});if(n.signal.aborted||r!==u)throw Ht();let o=n.collaboration?await Bt(t,e,i.pageId,n.collaboration.scopeId,n.signal):void 0;if(n.signal.aborted||r!==u)throw Ht();return{pageId:i.pageId,...o===void 0?{}:{collaborationRoomId:o},commit:()=>{n.signal.aborted||r!==u||(c=i.pageId,l=o)}}}})}}}function Rt(e){let t=new kt(e.client,e.session,{origin:e.request.location.origin}),n=e.request.collaboration?.cursors===!0||e.request.collaboration?.chat===!0;return{pageId:e.pageId,session:e.session,repository:t,...n?{collaborationRepository:new Pt(e.client,e.session,{origin:e.request.location.origin})}:{},...e.roomId===void 0?{}:{collaborationRoomId:e.roomId},resolvePage:e.resolvePage,allowedStagingHosts:[e.request.location.hostname]}}function zt(e,t){return{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname,...e.emailToken===void 0?{}:{emailToken:e.emailToken},forceRefreshToken:t,signal:e.signal}}async function Bt(e,t,n,r,i=t.signal){return e.resolveCollaborationRoom?e.resolveCollaborationRoom({invitationId:t.invitationId,pageId:n,scopeId:r,origin:t.location.origin,signal:i}):`${n}:${r}`.slice(0,512)}function Vt(e,t){if(!e||e.invitationId!==t||!e.authUserId||!e.reviewerId||!e.projectId)throw Error(`Convex returned an invalid reviewer session`);return structuredClone(e)}function Ht(){return Object.assign(Error(`Review page resolution was superseded`),{code:`PAGE_SWAP_SUPERSEDED`})}var Z=class extends Error{code;status;constructor(e,t,n){super(t),this.code=e,this.status=n,this.name=`HostedBootstrapError`}};function Ut(e={}){return Wt(e)}function Wt(t={},n={}){let r=e(t.serviceUrl??`https://review.01.works`),i=t.fetch??globalThis.fetch,a=n.instantRuntimeFactory??lt,o=n.convexRuntimeFactory??Lt,s=n.now??Date.now,c=new Map,l=n.reviewerSessionStorage===void 0?en():n.reviewerSessionStorage;if(typeof i!=`function`)throw Error(`Visual Review bootstrap requires the Fetch API`);return{async resolve(e){let t=Jt(e),u=await Zt(r,i,t,e.signal),d=s(),f={serviceUrl:r,...n.instantAuthDatabaseFactory===void 0?{}:{databaseFactory:n.instantAuthDatabaseFactory},redeemEmailInvitation:e=>qt(r,i,e),acceptInvitation:async e=>{let t=await i(`${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 Q(t);if(!t.ok)throw new Z($(n,`error`)??`INVITATION_ACCEPT_FAILED`,$(n,`message`)??`리뷰 초대 수락에 실패했습니다.`,t.status)},resolveReviewPage:e=>Xt(r,i,e),...e.collaboration?.cursors===!0||e.collaboration?.chat===!0?{resolveCollaborationRoom:e=>Yt(r,i,e)}:{}},p=u.apiVersion===2?await Gt({config:u,convexRuntimeFactory:o,fetcher:i,memorySessions:c,request:e,sessionStorage:l,serviceUrl:r}):await a(u.instantAppId,f).resolve(e),m=p.resolvePage;if(!m)return p;let h=async t=>{await Zt(r,i,{invitationId:e.invitationId,origin:t.location.origin,pathname:t.location.pathname},t.signal),d=s()};return{...p,resolvePage:async e=>(s()-d>=3e5&&await h(e),m(e))}}}}async function Gt(e){let t=$t(e.serviceUrl,e.request.location.origin,e.request.invitationId),n;if(e.request.emailToken?(await _t(e.request.authHost,e.request.signal,e.request.styleNonce),n=await qt(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}),nn(e.sessionStorage,e.memorySessions,t,n)):n=tn(e.sessionStorage,e.memorySessions,t),!n)throw new Z(`INVITATION_EMAIL_REQUIRED`,`초대받은 이메일의 링크를 다시 열어 주세요.`,401);return e.convexRuntimeFactory(e.config.convexUrl,{fetchAccessToken:r=>Kt(e.serviceUrl,e.fetcher,n,r,()=>rn(e.sessionStorage,e.memorySessions,t))}).resolve(e.request)}async function Kt(e,t,n,r,i){let a=await t(`${e}/v1/convex/token`,{method:`POST`,headers:{accept:`application/json`,authorization:`Bearer ${n}`,"content-type":`application/json`},body:JSON.stringify({invitationId:r.invitationId,origin:r.origin,pathname:r.pathname}),cache:`no-store`,credentials:`omit`,signal:r.signal}),o=await Q(a),s=$(o,`token`);if(!a.ok||!s||s.length>16e3)throw[401,403,409,410].includes(a.status)&&i(),new Z($(o,`error`)??`CONVEX_AUTH_FAILED`,$(o,`message`)??`리뷰 인증을 갱신하지 못했습니다.`,a.status);return s}async function qt(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 Q(r);if(!r.ok)throw new Z($(i,`error`)??`INVITATION_REDEEM_FAILED`,$(i,`message`)??`리뷰 초대를 시작하지 못했습니다.`,r.status);let a=$(i,`refreshToken`);if(!a||a.length>4096)throw new Z(`INVALID_INVITATION_REDEEM_RESPONSE`,`잘못된 초대 인증 응답입니다.`,502);return a}function Jt(e){return{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname}}async function Yt(e,t,n){let r=await t(`${e}/v1/collaboration/room`,{method:`POST`,headers:{accept:`application/json`,authorization:`Bearer ${n.refreshToken}`,"content-type":`application/json`},body:JSON.stringify({invitationId:n.invitationId,pageId:n.pageId,scopeId:n.scopeId}),cache:`no-store`,credentials:`omit`,signal:n.signal}),i=await Q(r);if(!r.ok)throw new Z($(i,`error`)??`COLLABORATION_ROOM_FAILED`,$(i,`message`)??`실시간 협업 연결에 실패했습니다.`,r.status);if(!i||typeof i!=`object`||Array.isArray(i))throw new Z(`INVALID_COLLABORATION_ROOM`,`잘못된 협업 응답입니다.`,502);let a=i,o=$(a,`id`);if(!o||!/^vr_[A-Za-z0-9_-]{43}$/u.test(o)||!Number.isSafeInteger(a.expiresAt))throw new Z(`INVALID_COLLABORATION_ROOM`,`잘못된 협업 응답입니다.`,502);return{id:o,expiresAt:a.expiresAt}}async function Xt(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 Q(r);throw new Z($(i,`error`)??`PAGE_RESOLVE_FAILED`,$(i,`message`)??`리뷰 페이지를 준비하지 못했습니다.`,r.status)}async function Zt(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 Q(i);if(!i.ok)throw new Z($(a,`error`)??`BOOTSTRAP_FAILED`,$(a,`message`)??`Visual Review bootstrap에 실패했습니다.`,i.status);return Qt(a)}function Qt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new Z(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let t=e;if(typeof t.apiVersion==`number`&&t.apiVersion!==1&&t.apiVersion!==2)throw new Z(`UNSUPPORTED_SERVICE_VERSION`,`이 Visual Review 위젯 버전은 더 이상 지원되지 않습니다. 사이트의 @01.works/visual-review를 업데이트해 주세요.`,502);if(t.apiVersion===2){let e=an(t.convexUrl);if(t.provider!==`convex`||!e)throw new Z(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{apiVersion:2,provider:`convex`,convexUrl:e}}let n=$(t,`instantAppId`);if(t.apiVersion!==1||!n||!on(n))throw new Z(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{apiVersion:1,instantAppId:n}}function $t(e,t,n){return`01works.visual-review.convex-session.v1:${JSON.stringify([e,t,n])}`}function en(){try{return globalThis.sessionStorage??null}catch{return null}}function tn(e,t,n){try{let t=e?.getItem(n);if(t)return t}catch{}return t.get(n)??null}function nn(e,t,n,r){t.set(n,r);try{e?.setItem(n,r)}catch{}}function rn(e,t,n){t.delete(n);try{e?.removeItem(n)}catch{}}function an(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 Q(e){try{return await e.json()}catch{throw new Z(`INVALID_BOOTSTRAP_RESPONSE`,`JSON bootstrap 응답이 필요합니다.`,502)}}function $(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n=e[t];return typeof n==`string`&&n.trim()?n.trim():null}function on(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{Ut as createHostedReviewRuntime};
|
|
13
|
+
`,q=Object.freeze({resolveSession:i(`reviews:resolveSession`),pageSnapshot:i(`reviews:pageSnapshot`),projectSnapshot:i(`reviews:projectSnapshot`),createComment:i(`reviews:createComment`),createReply:i(`reviews:createReply`),presenceList:i(`presence:list`),presenceUpdate:i(`presence:update`),presenceDisconnect:i(`presence:disconnect`),screenshotUploadUrl:i(`screenshots:generateUploadUrl`),screenshotCommit:i(`screenshots:commitUpload`),screenshotDiscard:i(`screenshots:discardUpload`)});Object.freeze({catalog:i(`owners:catalog`),listProjects:i(`owners:listProjects`),projectOverview:i(`owners:projectOverview`),createProject:i(`owners:createProject`),deleteProject:i(`owners:deleteProject`),addOrigin:i(`owners:addOrigin`),removeOrigin:i(`owners:removeOrigin`),createPage:i(`owners:createPage`),deletePage:i(`owners:deletePage`),upsertPageBuild:i(`owners:upsertPageBuild`),createInvitation:i(`owners:createInvitation`),revokeInvitation:i(`owners:revokeInvitation`),setCommentStatus:i(`owners:setCommentStatus`),createReply:i(`owners:createReply`),deleteComment:i(`owners:deleteComment`),deleteReply:i(`owners:deleteReply`),screenshotDownload:i(`screenshots:ownerDownload`)});var At=class{client;session;#e;#t;#n;constructor(e,t,n){this.client=e,this.session=t,this.#e=Y(n.invitationId??t.invitationId,`invitationId`),this.#t=Pt(n.origin),this.#n=n.fetch??globalThis.fetch.bind(globalThis)}async attachScreenshot(e,t,n){Y(e,`pageId`);let r=Y(t,`commentId`);if(n.bytes.byteLength===0||n.bytes.byteLength>15e5)throw Error(`Screenshot size is invalid`);let i=await this.client.mutation(q.screenshotUploadUrl,{...this.#r(),commentId:r}),a=await this.#n(i,{method:`POST`,headers:{"content-type":n.contentType},body:jt(n.bytes)});if(!a.ok)throw Error(`Screenshot upload failed`);let o=await a.json();if(typeof o.storageId!=`string`||!o.storageId)throw Error(`Screenshot upload returned an invalid storage ID`);try{await this.client.mutation(q.screenshotCommit,{...this.#r(),commentId:r,storageId:o.storageId,contentType:n.contentType,width:n.width,height:n.height})}catch(e){throw await this.client.mutation(q.screenshotDiscard,{...this.#r(),commentId:r,storageId:o.storageId}).catch(()=>void 0),e}}async getSnapshot(e){return Nt(await this.client.query(q.pageSnapshot,{...this.#r(),pageId:Y(e,`pageId`)}))}async getProjectSnapshot(e){return this.#i(e),structuredClone(await this.client.query(q.projectSnapshot,{...this.#r(),projectId:e}))}subscribe(e,t,n){return this.client.onUpdate(q.pageSnapshot,{...this.#r(),pageId:Y(e,`pageId`)},e=>t(Nt(e)),e=>n?.(J(e)))}subscribeProject(e,t,n){return this.#i(e),this.client.onUpdate(q.projectSnapshot,{...this.#r(),projectId:e},e=>t(structuredClone(e)),e=>n?.(J(e)))}async mutate(e,t){switch(t.type){case`comment.upsert`:{let n=t.comment;if(n.pageId!==e)throw Error(`Comment page mismatch`);if(n.authorId!==this.session.reviewerId)throw Error(`Comment author mismatch`);if(n.status!==`open`||n.resolvedAt!==void 0||n.resolvedById!==void 0||n.createdAt!==n.updatedAt)throw Error(`Only new open comments can be created by a reviewer`);let r=g(n.body).trim(),i=d(n.target),a=n.scope===void 0?void 0:ne(n.scope);await this.client.mutation(q.createComment,{...this.#r(),pageId:e,commentId:n.id,body:r,targetJson:JSON.stringify(i.publicTarget),sourceContextJson:i.sourceContextJson,...a===void 0?{}:{scopeJson:JSON.stringify(a)}});return}case`reply.upsert`:{let e=t.reply;if(e.authorId!==this.session.reviewerId)throw Error(`Reply author mismatch`);if(e.createdAt!==e.updatedAt)throw Error(`Reply edits require an owner command`);await this.client.mutation(q.createReply,{...this.#r(),commentId:e.commentId,replyId:e.id,body:g(e.body,`Reply body`).trim()});return}case`comment.delete`:throw Error(`Comment deletion requires an owner command`);case`reply.delete`:throw Error(`Reply deletion requires an owner command`)}}#r(){return{invitationId:this.#e,origin:this.#t}}#i(e){if(!e.trim()||e!==this.session.projectId)throw Error(`Project does not belong to the reviewer session`)}};function jt(e){let t=new Uint8Array(e.byteLength);return t.set(e),t.buffer}function J(e){let t=Mt(e);return t===`UNAUTHENTICATED`||t===`INVITATION_EXPIRED`?{type:`access-lost`,code:`session-expired`,recovery:`reauthenticate`,clearSnapshot:!0}:t===`INVITATION_REVOKED`||t===`MEMBERSHIP_REVOKED`?{type:`access-lost`,code:`membership-revoked`,recovery:`reauthenticate`,clearSnapshot:!0}:t===`ORIGIN_MISMATCH`||t===`ORIGIN_NOT_ALLOWED`||t===`INVITATION_REQUIRED`?{type:`access-lost`,code:`permission-denied`,recovery:`reauthenticate`,clearSnapshot:!0}:{type:`error`,code:e instanceof Error?`transport`:`unknown`,recovery:`retry`,clearSnapshot:!0}}function Mt(e){if(!e||typeof e!=`object`)return;let t=e.data;if(typeof t==`string`)return t;if(t&&typeof t==`object`){let e=t.code;if(typeof e==`string`)return e}}function Nt(e){return structuredClone(e)}function Y(e,t){let n=e.trim();if(!n)throw Error(`${t} is required`);return n}function Pt(e){let t=Y(e,`origin`);try{let e=new URL(t);if(e.origin!==t)throw Error();return e.origin}catch{throw Error(`A valid browser origin is required`)}}var Ft=class{client;session;#e=new Map;#t;#n;#r;#i;#a;#o;constructor(e,t,n){this.client=e,this.session=t,this.#t=(n.invitationId??t.invitationId).trim(),this.#n=new URL(n.origin).origin,this.#r=It(n.cursorThrottleMs??80,40,1e3),this.#i=It(n.heartbeatMs??1e4,2e3,2e4),this.#a=n.now??Date.now,this.#o=n.sessionId??(()=>globalThis.crypto.randomUUID())}subscribe(e,t,n,r){let i=!1,a=[],o=this.#s(e,t.roomId),s=()=>{i||n({pageId:e,peers:structuredClone(a),messages:[]})},c=t.cursors||t.chat?this.client.onUpdate(q.presenceList,{...this.#d(),pageId:e,roomId:t.roomId},e=>{let t=this.#a();a=e.filter(({peerId:e,expiresAt:n})=>e!==o.sessionId&&n>t).map(({expiresAt:e,...t})=>t).sort((e,t)=>e.displayName.localeCompare(t.displayName)||e.peerId.localeCompare(t.peerId)),s()},e=>r?.(J(e))):()=>void 0;return queueMicrotask(s),()=>{i||(i=!0,c(),this.#u(o))}}publishPresence(e,t,n){let r=this.#e.get(X(e,t));!r||r.stopped||(r.latest={...n,reviewerId:this.session.reviewerId,displayName:this.session.displayName},this.#c(r))}async sendMessage(e,t){let n=[...this.#e.values()].find(t=>t.pageId===e);n?.latest&&(n.latest={...n.latest,cursorChat:t.body.slice(0,4e3)},await this.#l(n))}#s(e,t){let n=X(e,t),r=this.#e.get(n);r&&this.#u(r);let i={pageId:e,roomId:t,sessionId:this.#o(),stopped:!1,lastSentAt:-1/0,inFlight:!1};return i.heartbeatTimer=setInterval(()=>{i.latest&&this.#l(i)},this.#i),this.#e.set(n,i),i}#c(e){if(e.inFlight||e.flushTimer||e.stopped)return;let t=Math.max(0,this.#r-(this.#a()-e.lastSentAt));if(t===0){this.#l(e);return}e.flushTimer=setTimeout(()=>{e.flushTimer=void 0,this.#l(e)},t)}async#l(e){if(e.stopped||e.inFlight||!e.latest)return;e.inFlight=!0;let t=e.latest;e.latest=void 0;try{await this.client.mutation(q.presenceUpdate,{...this.#d(),pageId:e.pageId,roomId:e.roomId,sessionId:e.sessionId,color:t.color,active:t.active,...t.pathname===void 0?{}:{pathname:t.pathname},...t.cursorX===void 0?{}:{cursorX:t.cursorX},...t.cursorY===void 0?{}:{cursorY:t.cursorY},...t.viewportWidth===void 0?{}:{viewportWidth:t.viewportWidth},...t.viewportHeight===void 0?{}:{viewportHeight:t.viewportHeight},...t.cursorChat===void 0?{}:{cursorChat:t.cursorChat}}),e.lastSentAt=this.#a()}finally{e.inFlight=!1,e.latest&&this.#c(e)}}#u(e){e.stopped||(e.stopped=!0,e.flushTimer&&clearTimeout(e.flushTimer),e.heartbeatTimer&&clearInterval(e.heartbeatTimer),this.#e.delete(X(e.pageId,e.roomId)),this.client.mutation(q.presenceDisconnect,{...this.#d(),sessionId:e.sessionId}).catch(()=>void 0))}#d(){return{invitationId:this.#t,origin:this.#n}}};function X(e,t){return`${e}\u0000${t}`}function It(e,t,n){return Number.isFinite(e)?Math.min(n,Math.max(t,Math.round(e))):t}function Lt(e,t){let n=e.trim();if(!/^https:\/\/[^/]+$/.test(n))throw Error(`A valid HTTPS Convex deployment URL is required`);let r=new a(n);return r.setAuth(t),r}function Rt(e,t){let n=e.trim();if(!n)throw Error(`Convex deployment URL is required`);return{async resolve(e){let r=await t.fetchAccessToken(Bt(e,!1));if(!r)throw Error(`Convex review authentication is required`);let i=r,a=(t.clientFactory??Lt)(n,async({forceRefreshToken:n})=>{if(!n&&i){let e=i;return i=null,e}return t.fetchAccessToken({...Bt(e,n),signal:new AbortController().signal})}),o=await a.mutation(q.resolveSession,{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname}),s=Ht(o.session,e.invitationId),c=o.pageId,l=e.collaboration?await Vt(t,e,c,e.collaboration.scopeId):void 0,u=0;return zt({client:a,session:s,request:e,pageId:c,roomId:l,resolvePage:async n=>{if(n.location.origin!==e.location.origin)throw Error(`Convex review session cannot move to another origin`);let r=++u,i=await a.mutation(q.resolveSession,{invitationId:e.invitationId,origin:n.location.origin,pathname:n.location.pathname});if(n.signal.aborted||r!==u)throw Ut();let o=n.collaboration?await Vt(t,e,i.pageId,n.collaboration.scopeId,n.signal):void 0;if(n.signal.aborted||r!==u)throw Ut();return{pageId:i.pageId,...o===void 0?{}:{collaborationRoomId:o},commit:()=>{n.signal.aborted||r!==u||(c=i.pageId,l=o)}}}})}}}function zt(e){let t=new At(e.client,e.session,{origin:e.request.location.origin}),n=e.request.collaboration?.cursors===!0||e.request.collaboration?.chat===!0;return{pageId:e.pageId,session:e.session,repository:t,...n?{collaborationRepository:new Ft(e.client,e.session,{origin:e.request.location.origin})}:{},...e.roomId===void 0?{}:{collaborationRoomId:e.roomId},resolvePage:e.resolvePage,allowedStagingHosts:[e.request.location.hostname]}}function Bt(e,t){return{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname,...e.emailToken===void 0?{}:{emailToken:e.emailToken},forceRefreshToken:t,signal:e.signal}}async function Vt(e,t,n,r,i=t.signal){return e.resolveCollaborationRoom?e.resolveCollaborationRoom({invitationId:t.invitationId,pageId:n,scopeId:r,origin:t.location.origin,signal:i}):`${n}:${r}`.slice(0,512)}function Ht(e,t){if(!e||e.invitationId!==t||!e.authUserId||!e.reviewerId||!e.projectId)throw Error(`Convex returned an invalid reviewer session`);return structuredClone(e)}function Ut(){return Object.assign(Error(`Review page resolution was superseded`),{code:`PAGE_SWAP_SUPERSEDED`})}var Z=class extends Error{code;status;constructor(e,t,n){super(t),this.code=e,this.status=n,this.name=`HostedBootstrapError`}};function Wt(e={}){return Gt(e)}function Gt(t={},n={}){let r=e(t.serviceUrl??`https://review.01.works`),i=t.fetch??globalThis.fetch,a=n.instantRuntimeFactory??lt,o=n.convexRuntimeFactory??Rt,s=n.now??Date.now,c=new Map,l=n.reviewerSessionStorage===void 0?sn():n.reviewerSessionStorage;if(typeof i!=`function`)throw Error(`Visual Review bootstrap requires the Fetch API`);return{async resolve(e){let t=$t(e),u=await nn(r,i,t,e.signal),d=s(),f={serviceUrl:r,...n.instantAuthDatabaseFactory===void 0?{}:{databaseFactory:n.instantAuthDatabaseFactory},redeemEmailInvitation:e=>Yt(r,i,e),acceptInvitation:async e=>{let t=await i(`${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 Q(t);if(!t.ok)throw new Z($(n,`error`)??`INVITATION_ACCEPT_FAILED`,$(n,`message`)??`리뷰 초대 수락에 실패했습니다.`,t.status)},resolveReviewPage:e=>tn(r,i,e),...e.collaboration?.cursors===!0||e.collaboration?.chat===!0?{resolveCollaborationRoom:e=>en(r,i,e)}:{}},p=u.apiVersion===2?await Kt({config:u,convexRuntimeFactory:o,fetcher:i,memorySessions:c,request:e,sessionStorage:l,serviceUrl:r}):{...await a(u.instantAppId,f).resolve(e),sessionScope:`browser`,sessionExpiresAt:u.invitationExpiresAt},m=p.resolvePage;if(!m)return p;let h=async t=>{await nn(r,i,{invitationId:e.invitationId,origin:t.location.origin,pathname:t.location.pathname},t.signal),d=s()};return{...p,resolvePage:async e=>(s()-d>=3e5&&await h(e),m(e))}}}}async function Kt(e){let t=on(e.serviceUrl,e.request.location.origin,e.request.invitationId),n;if(e.request.emailToken){await _t(e.request.authHost,e.request.signal,e.request.styleNonce);try{n=await Yt(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})}catch(t){if(!(t instanceof Z)||t.code!==`INVITATION_TOKEN_USED`)throw t;n=await qt(e)}ln(e.sessionStorage,e.memorySessions,t,n)}else n=cn(e.sessionStorage,e.memorySessions,t);return n||(n=await qt(e),ln(e.sessionStorage,e.memorySessions,t,n)),{...await e.convexRuntimeFactory(e.config.convexUrl,{fetchAccessToken:r=>Jt(e.serviceUrl,e.fetcher,n,r,()=>un(e.sessionStorage,e.memorySessions,t))}).resolve(e.request),sessionScope:`tab`,sessionExpiresAt:e.config.invitationExpiresAt,clearLocalSession:()=>un(e.sessionStorage,e.memorySessions,t)}}async function qt(e){let t={invitationId:e.request.invitationId,pathname:e.request.location.pathname,signal:e.request.signal};return vt(e.request.authHost,e.request.signal,{requestCode:()=>Xt(e.serviceUrl,e.fetcher,t),verifyCode:(n,r)=>Zt(e.serviceUrl,e.fetcher,{...t,challengeId:n,code:r})},e.request.styleNonce)}async function Jt(e,t,n,r,i){let a=await t(`${e}/v1/convex/token`,{method:`POST`,headers:{accept:`application/json`,authorization:`Bearer ${n}`,"content-type":`application/json`},body:JSON.stringify({invitationId:r.invitationId,origin:r.origin,pathname:r.pathname}),cache:`no-store`,credentials:`omit`,signal:r.signal}),o=await Q(a),s=$(o,`token`);if(!a.ok||!s||s.length>16e3)throw[401,403,409,410].includes(a.status)&&i(),new Z($(o,`error`)??`CONVEX_AUTH_FAILED`,$(o,`message`)??`리뷰 인증을 갱신하지 못했습니다.`,a.status);return s}async function Yt(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 Q(r);if(!r.ok)throw new Z($(i,`error`)??`INVITATION_REDEEM_FAILED`,$(i,`message`)??`리뷰 초대를 시작하지 못했습니다.`,r.status);let a=$(i,`refreshToken`);if(!a||a.length>4096)throw new Z(`INVALID_INVITATION_REDEEM_RESPONSE`,`잘못된 초대 인증 응답입니다.`,502);return a}async function Xt(e,t,n){let r=await Qt(e,t,`start`,n),i=$(r,`challengeId`),a=$(r,`emailHint`);if(!i||!a)throw new Z(`INVALID_RECOVERY_RESPONSE`,`잘못된 복구 응답입니다.`,502);return{challengeId:i,emailHint:a}}async function Zt(e,t,n){let r=$(await Qt(e,t,`verify`,n),`refreshToken`);if(!r||r.length>4096)throw new Z(`INVALID_RECOVERY_RESPONSE`,`잘못된 복구 응답입니다.`,502);return r}async function Qt(e,t,n,r){let{signal:i,...a}=r,o=await t(`${e}/v1/invitations/recovery/${n}`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify(a),cache:`no-store`,credentials:`omit`,signal:i}),s=await Q(o);if(!o.ok)throw new Z($(s,`error`)??`RECOVERY_FAILED`,$(s,`message`)??`리뷰 접속을 복구하지 못했습니다.`,o.status);if(!s||typeof s!=`object`||Array.isArray(s))throw new Z(`INVALID_RECOVERY_RESPONSE`,`잘못된 복구 응답입니다.`,502);return s}function $t(e){return{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname}}async function en(e,t,n){let r=await t(`${e}/v1/collaboration/room`,{method:`POST`,headers:{accept:`application/json`,authorization:`Bearer ${n.refreshToken}`,"content-type":`application/json`},body:JSON.stringify({invitationId:n.invitationId,pageId:n.pageId,scopeId:n.scopeId}),cache:`no-store`,credentials:`omit`,signal:n.signal}),i=await Q(r);if(!r.ok)throw new Z($(i,`error`)??`COLLABORATION_ROOM_FAILED`,$(i,`message`)??`실시간 협업 연결에 실패했습니다.`,r.status);if(!i||typeof i!=`object`||Array.isArray(i))throw new Z(`INVALID_COLLABORATION_ROOM`,`잘못된 협업 응답입니다.`,502);let a=i,o=$(a,`id`);if(!o||!/^vr_[A-Za-z0-9_-]{43}$/u.test(o)||!Number.isSafeInteger(a.expiresAt))throw new Z(`INVALID_COLLABORATION_ROOM`,`잘못된 협업 응답입니다.`,502);return{id:o,expiresAt:a.expiresAt}}async function tn(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 Q(r);throw new Z($(i,`error`)??`PAGE_RESOLVE_FAILED`,$(i,`message`)??`리뷰 페이지를 준비하지 못했습니다.`,r.status)}async function nn(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 Q(i);if(!i.ok)throw new Z($(a,`error`)??`BOOTSTRAP_FAILED`,$(a,`message`)??`Visual Review bootstrap에 실패했습니다.`,i.status);return rn(a)}function rn(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new Z(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let t=e;if(typeof t.apiVersion==`number`&&t.apiVersion!==1&&t.apiVersion!==2)throw new Z(`UNSUPPORTED_SERVICE_VERSION`,`이 Visual Review 위젯 버전은 더 이상 지원되지 않습니다. 사이트의 @01.works/visual-review를 업데이트해 주세요.`,502);if(t.apiVersion===2){let e=dn(t.convexUrl),n=an(t.invitationExpiresAt);if(t.provider!==`convex`||!e||n===null)throw new Z(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{apiVersion:2,provider:`convex`,convexUrl:e,...n===void 0?{}:{invitationExpiresAt:n}}}let n=$(t,`instantAppId`),r=an(t.invitationExpiresAt);if(t.apiVersion!==1||!n||!fn(n)||r===null)throw new Z(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{apiVersion:1,instantAppId:n,...r===void 0?{}:{invitationExpiresAt:r}}}function an(e){if(e!==void 0)return Number.isSafeInteger(e)&&e>0?e:null}function on(e,t,n){return`01works.visual-review.convex-session.v1:${JSON.stringify([e,t,n])}`}function sn(){try{return globalThis.sessionStorage??null}catch{return null}}function cn(e,t,n){try{let t=e?.getItem(n);if(t)return t}catch{}return t.get(n)??null}function ln(e,t,n,r){t.set(n,r);try{e?.setItem(n,r)}catch{}}function un(e,t,n){t.delete(n);try{e?.removeItem(n)}catch{}}function dn(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 Q(e){try{return await e.json()}catch{throw new Z(`INVALID_BOOTSTRAP_RESPONSE`,`JSON bootstrap 응답이 필요합니다.`,502)}}function $(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n=e[t];return typeof n==`string`&&n.trim()?n.trim():null}function fn(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{Wt as createHostedReviewRuntime};
|
package/dist/index.d.ts
CHANGED
|
@@ -250,6 +250,12 @@ export interface ReviewRuntimeContext {
|
|
|
250
250
|
collaborationRepository?: VisualReviewCollaborationRepository;
|
|
251
251
|
collaborationRoomId?: string;
|
|
252
252
|
allowedStagingHosts: string[];
|
|
253
|
+
/** Scope must not outlive the runtime's reusable authentication session. */
|
|
254
|
+
sessionScope?: 'tab' | 'browser';
|
|
255
|
+
/** Upper bound for browser-scoped activation. Ignored for tab-scoped sessions. */
|
|
256
|
+
sessionExpiresAt?: number;
|
|
257
|
+
/** Clears provider-owned reviewer credentials for an explicit local exit. */
|
|
258
|
+
clearLocalSession?(): void;
|
|
253
259
|
/**
|
|
254
260
|
* Re-resolve only the page-specific context after a client-side route change.
|
|
255
261
|
* Omit this method to make the installation fall back to a full restart.
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./install-
|
|
1
|
+
import{t as e}from"./install-Dh6WT91E.js";export{e as installVisualReview};
|
|
@@ -0,0 +1,2 @@
|
|
|
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,v=null,y=!1,b=!1,x=null,S=null,E=null,O=t(e.serviceUrl??`https://review.01.works`),A=e.activationParam??`visual-review`,j=ue(window),M=de(window),P=w(window.location);if(!(ie(O,A,P,M,j,e.runtime!==void 0)??T(ne(O,P.origin)))){let t={reason:`missing-activation`,origin:P.origin};return N(e.build).mode===`development`&&c(document,t.origin),l(e.onInactive,t),n()}let F=document.baseURI,I=new WeakMap,L=new Map,R=pe(e.styleNonce,document),z=C(window.location,A),B=ee(window,e=>{let t=C(e,A);if(t===z)return;let n=k(A,e.href);n&&(b=!1,L.set(e.origin,n)),z=t,V(e)}),ce=e=>{if(!(r||!v)){if(e===`membership-revoked`){let e=w(window.location),t=L.get(e.origin);t&&(D(O,e.origin,t),L.delete(e.origin),K(O,e.origin,M,j,t));return}z=C(window.location,A),W()}};return{ready:W(),refresh(){return r?Promise.resolve(null):(z=C(window.location,A),V(w(window.location),!0))},dispose(){r||(r=!0,i+=1,U(),v?.remove(),v=null,E=null,S?.remove(),S=null,L.clear(),x?.dispose(),x=null,B.unsubscribe())}};function V(e,t=!1){return!v||!E||E.origin!==e.origin||k(A,e.href)?W():H(v,E,e,t)}function H(t,n,r,c){let l=++i;a!==o&&a?.abort();let d=new AbortController;a=d;let f=u(e.build,r),p=(async()=>{try{let i=await oe(n.resolvePage({location:r,signal:d.signal,collaboration:{cursors:e.collaboration?.cursors===!0,chat:e.collaboration?.chat===!0,scopeId:f}}),d.signal);return Q(l,d)?(i.commit?.(),t.setPage({pageId:i.pageId,collaboration:{roomId:i.collaborationRoomId,scopeId:f}},{reload:c}),t.isConnected||document.body?.append(t),t):$(l)}catch{return Q(l,d)?W():$(l)}})();return s=p,p}function U(){a?.abort(),o?.abort(),a=null,o=null}function W(){if(b&&!k(A,w(window.location).href))return Promise.resolve(null);let t=++i;U(),x?.suspendSession(),v?.remove(),v=null,E=null,S?.remove();let n=new AbortController,r=document.createElement(`div`);r.dataset.agencyReviewRoot=``,a=n,o=n,S=r;let c=q(t,n,r);return s=c,c.then(r=>{r&&Q(t,n)&&v===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(m(a,`AUTH_CANCELLED`))return i.remove(),S===i&&(S=null),null;let o=I.get(i),s=o?.[3];if(Z(a,i),h(s)&&m(a,`INVITATION_EMAIL_REQUIRED`)&&!y){let e=o?.[1]??w(window.location).origin,t=o?.[2];return t&&(L.delete(e),K(O,e,M,j,t)),i.remove(),S===i&&(S=null),null}let c=fe(a,o?.[2]),u=o?.[1]??w(window.location).origin,d=m(a,`ORIGIN_NOT_ALLOWED`);if(d&&l(e.onInactive,{reason:`origin-not-allowed`,origin:u}),!h(s)||y||!g(a)){let{originNotAllowedMessage:e,renderBootstrapError:o}=await import(`./bootstrap-error-B30Je5Pg.js`);if(!Q(t,n))return i.remove(),$(t);let s=_(a)?void 0:()=>{r||S!==i||(z=C(window.location,A),W())};o(i,d?e(u):c.message,R,s)}else i.remove(),S===i&&(S=null);return e.onError?.(c),window.dispatchEvent(new CustomEvent(`visual-review:error`,{detail:c})),null}}async function J(t,n,r){let i=w(window.location),a=ie(O,A,i,M,j,e.runtime!==void 0),o=te(L.get(i.origin)),s=T(ne(O,i.origin)),c=a?.source===`url`?a:s??o??a;if(!c)return I.delete(r),r.remove(),S===r&&(S=null),null;let l=c.invitationId;I.set(r,[O,i.origin,l,c.source,c.emailToken]),c.source===`url`?(K(O,i.origin,M,j),L.set(i.origin,l),re(O,i.origin,l,c.emailToken),B.suppress(()=>ae(A))):c.source===`handoff`&&L.set(i.origin,l),z=C(window.location,A);let m=w(window.location),h=await oe((e.runtime??await d(O)).resolve({invitationId:l,emailToken:c.emailToken,location:m,signal:n.signal,authHost:r,styleNonce:R,collaboration:{cursors:e.collaboration?.cursors===!0,chat:e.collaboration?.chat===!0,scopeId:u(e.build,m)}}),n.signal);if(!Q(t,n))return null;D(O,i.origin,l),le(O,l,i,M,j,h.sessionScope??`browser`,h.sessionExpiresAt),c.source===`url`&&G(j,X(O,i.origin)),L.set(i.origin,l);let g=e.sourceContextResolver??await p(e.build,F,n.signal,R);if(!Q(t,n))return null;let{createActiveReviewSessionLifecycle:_,createReviewNavigationHandler:ee,mountReviewWidget:b}=await f(n.signal);if(!Q(t,n))return null;x??=_({window,document,storage:j,onExit:Y,onReauthenticationRequired:ce});let k=x.bindSession(l,X(O,i.origin),h.clearLocalSession);return Q(t,n)?(v=b({...h,collaboration:{cursors:e.collaboration?.cursors===!0&&!!(h.collaborationRepository&&h.collaborationRoomId),chat:e.collaboration?.chat===!0&&!!h.collaborationRepository,repository:h.collaborationRepository,roomId:h.collaborationRoomId,scopeId:u(e.build,i)},developerTools:e.developerTools?.codeContextCopy===!0||e.developerTools?.reactGrab===!0?{codeContextCopy:!0}:void 0,offset:e.offset,onExitReview:k,onNavigateToFeedback:ee(window,e.navigateToFeedback),sourceContextResolver:g,styleNonce:R,position:e.position}),x.attachWidget(v),E=h.resolvePage?{origin:i.origin,resolvePage:e=>h.resolvePage(e)}:null,r.remove(),S===r&&(S=null),y=!0,window.dispatchEvent(new CustomEvent(`visual-review:ready`,{detail:v})),v):null}function Y(e){let t=w(window.location).origin;b=!0,D(O,t,e),L.delete(t),K(O,t,M,j,e),i+=1,U(),v?.remove(),v=null,E=null,S?.remove(),S=null}function Z(e,t){if(!g(e))return;let n=I.get(t);if(!n)return;let[r,i,a]=n;D(r,i,a),L.get(i)===a&&L.delete(i),K(r,i,M,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)}}function u(e,t){return JSON.stringify([N(e).buildId,t.pathname,t.search])}async function d(e){let{createHostedReviewRuntime:t}=await import(`./hosted-runtime-D6Xuc19F.js`);return t({serviceUrl:e})}async function f(e){return M(import(`./active-review-mount-DtVtT0xd.js`),e,a,`리뷰 위젯을 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`)}async function p(e,t,n,r){let i=N(e),{createGeneratedSourceContextResolver:o}=await M(import(`./generated-source-context-D59o5CKS.js`),n,a,`리뷰 소스 정보를 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`);return o({build:i})}function m(e,t){return e instanceof Error&&`code`in e&&e.code===t}function h(e){return e===`tab-storage`||e===`browser-storage`||e===`legacy-storage`}function g(e){let t=v(e);return typeof t==`string`&&/^INVITATION_(?:EXPIRED|NOT_FOUND|REVOKED)$/.test(t)}function _(e){return g(e)||v(e)===`UNSUPPORTED_SERVICE_VERSION`}function v(e){return e instanceof Error&&`code`in e?e.code:void 0}const y=new WeakMap;function ee(e,t){let n=y.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),b(e)},patchedReplaceState:function(t,n,r){i.call(this,t,n,r),b(e)},popstateListener:()=>b(e),subscribers:a,suppressionDepth:0},y.set(e,n),x(t,`pushState`,n.patchedPushState),x(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),S(n.history,`pushState`,n.patchedPushState,n.originalPushStateDescriptor),S(n.history,`replaceState`,n.patchedReplaceState,n.originalReplaceStateDescriptor),y.delete(e)))}}}function b(e){let t=y.get(e);if(!t||t.suppressionDepth>0)return;let n=w(e.location);[...t.subscribers].forEach(e=>e(n))}function x(e,t,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:!0,value:n})}function S(e,t,n,r){if(Object.getOwnPropertyDescriptor(e,t)?.value===n){if(r){Object.defineProperty(e,t,r);return}delete e[t]}}function C(e,t){return`${e.origin}\n${e.pathname}\n${k(t,e.href)??``}`}function w(e){return new URL(e.href)}function te(e){return e?{invitationId:e,source:`memory`}:null}function T(e){return e?{invitationId:e.invitationId,emailToken:e.emailToken,source:`handoff`}:null}function E(e,t){return JSON.stringify([e,t])}function ne(e,t,n=Date.now()){let i=E(e,t),a=r.get(i);if(a){if(a.expiresAt>n)return a;clearTimeout(a.timeout),r.delete(i)}}function re(e,t,n,a,o=Date.now()){O(o);let s=E(e,t),c=r.get(s);for(c&&(clearTimeout(c.timeout),r.delete(s));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 l=o+i,u=setTimeout(()=>{r.get(s)?.expiresAt===l&&r.delete(s)},i);r.set(s,{invitationId:n,emailToken:a,expiresAt:l,timeout:u})}function D(e,t,n){let i=E(e,t),a=r.get(i);a?.invitationId===n&&(clearTimeout(a.timeout),r.delete(i))}function O(e){for(let[t,n]of r)n.expiresAt>e||(clearTimeout(n.timeout),r.delete(t))}function ie(e,t,n,r,i,a){let o=k(t,n.href);if(o)return{invitationId:o,emailToken:A(n.href)??void 0,source:`url`};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 k(e,t){let n=new URL(t),r=j(n.hash);return(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()||null}function A(e){let t=(j(new URL(e).hash)?.get(`visual-review-token`))?.trim();return t&&/^[A-Za-z0-9_-]{43}$/u.test(t)?t:null}function j(e){let t=e.startsWith(`#`)?e.slice(1):e,n=t.startsWith(`?`)?t.slice(1):t;return n.includes(`=`)?new URLSearchParams(n):null}function ae(e){let t=new URL(window.location.href),n=new Set([e,`visual-review`,`agency-review`,`agency-review-invite`,`visual-review-token`]),r=!1;n.forEach(e=>{t.searchParams.has(e)&&(t.searchParams.delete(e),r=!0)});let i=j(t.hash);if(i){n.forEach(e=>{i.has(e)&&(i.delete(e),r=!0)});let e=i.toString();t.hash=e?`#${e}`:``}r&&window.history.replaceState(window.history.state,``,`${t.pathname}${t.search}${t.hash}`)}function oe(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 M(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 N(e){let t=document.querySelector(`meta[name="visual-review-build"]`),n=document.querySelector(`meta[name="visual-review-commit"]`),r=V(I()),i=V(L());return{buildId:ce(e?.buildId)??B(t)??r??`unversioned`,gitCommit:R(e,n,i),generatedAt:e?.generatedAt,mode:e?.mode??F(P())??(Z(window.location.hostname)?`development`:`production`)}}function P(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_MODE}catch{return}}function F(e){return e===`development`||e===`preview`||e===`production`?e:void 0}function I(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_ID}catch{return}}function L(){try{return process.env.VISUAL_REVIEW_PUBLIC_GIT_COMMIT}catch{return}}function R(e,t,n){return e?.gitCommit===null?null:typeof e?.gitCommit==`string`?z(e.gitCommit):z(t?.content)??z(n)}function z(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 B(e){return V(e?.content)}function ce(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 le(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 ue(e){try{return e.localStorage}catch{return null}}function de(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 fe(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 pe(e,t){if(e!==void 0)return me(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`?me(t):void 0}function me(e){return e.trim()||void 0}export{e as n,t as r,s as t};
|
package/dist/react.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./install-
|
|
1
|
+
import{t as e}from"./install-Dh6WT91E.js";import{useEffect as t,useRef as n}from"react";function r({activationParam:r,build:i,collaboration:a,developerTools:o,enabled:s,navigateToFeedback:c,offset:l,onError:u,onInactive:d,onReady:f,position:p,runtime:m,serviceUrl:h,sourceContextResolver:g,styleNonce:_}){let v=n(u),y=n(d),b=n(f),x=n(null),S=i?.buildId,C=i?.gitCommit,w=i?.generatedAt,T=i?.mode,E=o?.codeContextCopy===!0||o?.reactGrab===!0,D=a?.cursors===!0,O=a?.chat===!0;return v.current=u,y.current=d,b.current=f,t(()=>{if(s===!1)return;let t=e({activationParam:r,build:S===void 0&&C===void 0&&w===void 0&&T===void 0?void 0:{buildId:S,gitCommit:C,generatedAt:w,mode:T},collaboration:D||O?{cursors:D,chat:O}:void 0,developerTools:E?{codeContextCopy:!0}:void 0,enabled:s,navigateToFeedback:c,offset:l,onError:e=>v.current?.(e),onInactive:e=>{let t=`${e.reason}\n${e.origin}`;x.current!==t&&(x.current=t,y.current?.(e))},onReady:e=>{x.current=null,b.current?.(e)},runtime:m,position:p,serviceUrl:h,sourceContextResolver:g,styleNonce:_});return()=>t.dispose()},[r,S,T,O,D,E,s,w,C,c,l?.x,l?.y,p,m,h,g,_]),null}r.displayName=`VisualReview`;export{r as VisualReview};
|
package/package.json
CHANGED
package/dist/install-DSA2Fpbw.js
DELETED
|
@@ -1,3 +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,_=null,v=!1,b=null,x=null,S=t(e.serviceUrl??`https://review.01.works`),E=e.activationParam??`visual-review`,k=ae(window),M=w(window.location);if(!(A(S,E,M,k,e.runtime!==void 0)??T(D(S,M.origin)))){let t={reason:`missing-activation`,origin:M.origin};return L(e.build).mode===`development`&&c(document,t.origin),l(e.onInactive,t),n()}let N=document.baseURI,I=new WeakMap,R=new Map,z=se(e.styleNonce,document),B=C(window.location,E),V=y(window,e=>{let t=C(e,E);if(t===B)return;let n=j(E,e.href);n&&R.set(e.origin,n),B=t,U(e)}),H=e=>{if(!(r||!_||e.target!==_)){if((e instanceof CustomEvent&&e.detail&&typeof e.detail==`object`&&`code`in e.detail?e.detail.code:void 0)===`membership-revoked`){let e=w(window.location),t=R.get(e.origin);t&&(O(S,e.origin,t),R.delete(e.origin),J(S,e.origin,k,t));return}B=C(window.location,E),K()}};return window.addEventListener(`visual-review:reauthenticate-required`,H),{ready:K(),refresh(){return r?Promise.resolve(null):(B=C(window.location,E),U(w(window.location),!0))},dispose(){r||(r=!0,i+=1,G(),_?.remove(),_=null,x=null,b?.remove(),b=null,R.clear(),V.unsubscribe(),window.removeEventListener(`visual-review:reauthenticate-required`,H))}};function U(e,t=!1){return!_||!x||x.origin!==e.origin||j(E,e.href)?K():W(_,x,e,t)}function W(t,n,r,c){let l=++i;a!==o&&a?.abort();let u=new AbortController;a=u;let f=d(e.build,r),p=(async()=>{try{let i=await F(n.resolvePage({location:r,signal:u.signal,collaboration:{cursors:e.collaboration?.cursors===!0,chat:e.collaboration?.chat===!0,scopeId:f}}),u.signal);return Z(l,u)?(i.commit?.(),t.setPage({pageId:i.pageId,collaboration:{roomId:i.collaborationRoomId,scopeId:f}},{reload:c}),t.isConnected||document.body?.append(t),t):Q(l)}catch{return Z(l,u)?K():Q(l)}})();return s=p,p}function G(){a?.abort(),o?.abort(),a=null,o=null}function K(){let t=++i;G(),_?.remove(),_=null,x=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&&Z(t,n)&&_===r&&e.onReady?.(r)}),c}async function q(t,n,i){try{let e=document.body??await re(document,n.signal);if(!Z(t,n))return Q(t);e.append(i);let r=await Y(t,n,i);return Z(t,n)?r:(i.remove(),Q(t))}catch(a){if(!Z(t,n))return i.remove(),Q(t);if(m(a,`AUTH_CANCELLED`))return i.remove(),b===i&&(b=null),null;let o=I.get(i),s=o?.[3];X(a,i);let c=oe(a,o?.[2]),d=o?.[1]??w(window.location).origin,f=m(a,`ORIGIN_NOT_ALLOWED`);if(f&&l(e.onInactive,{reason:`origin-not-allowed`,origin:d}),s!==`storage`||v||!h(a)){let{renderBootstrapError:e}=await import(`./bootstrap-error-BwIf8fUE.js`);if(!Z(t,n))return i.remove(),Q(t);let o=g(a)?void 0:()=>{r||b!==i||(B=C(window.location,E),K())};e(i,f?u(d):c.message,z,o)}else i.remove(),b===i&&(b=null);return e.onError?.(c),window.dispatchEvent(new CustomEvent(`visual-review:error`,{detail:c})),null}}async function Y(t,n,r){let i=w(window.location),a=A(S,E,i,k,e.runtime!==void 0),o=te(R.get(i.origin)),s=T(D(S,i.origin)),c=a?.source===`url`?a:s??o??a;if(!c)return I.delete(r),r.remove(),b===r&&(b=null),null;let l=c.invitationId;I.set(r,[S,i.origin,l,c.source,c.emailToken]),c.source===`url`?(J(S,i.origin,k),R.set(i.origin,l),ne(S,i.origin,l,c.emailToken),V.suppress(()=>P(E))):c.source===`handoff`&&R.set(i.origin,l),B=C(window.location,E);let u=w(window.location),m=await F((e.runtime??await f(S)).resolve({invitationId:l,emailToken:c.emailToken,location:u,signal:n.signal,authHost:r,styleNonce:z,collaboration:{cursors:e.collaboration?.cursors===!0,chat:e.collaboration?.chat===!0,scopeId:d(e.build,u)}}),n.signal);if(!Z(t,n))return null;O(S,i.origin,l),ie(S,l,i,k),R.set(i.origin,l);let h=e.sourceContextResolver??await ee(e.build,N,n.signal,z);if(!Z(t,n))return null;let{mountReviewWidget:g}=await p(n.signal);return Z(t,n)?(_=g({...m,collaboration:{cursors:e.collaboration?.cursors===!0&&!!(m.collaborationRepository&&m.collaborationRoomId),chat:e.collaboration?.chat===!0&&!!m.collaborationRepository,repository:m.collaborationRepository,roomId:m.collaborationRoomId,scopeId:d(e.build,i)},developerTools:e.developerTools?.codeContextCopy===!0||e.developerTools?.reactGrab===!0?{codeContextCopy:!0}:void 0,offset:e.offset,onNavigateToFeedback:async t=>{let n=new URL(t,window.location.href);if(n.origin!==window.location.origin)throw Error(`Visual Review route navigation must stay on the staging origin`);if(e.navigateToFeedback){await e.navigateToFeedback(n.href);return}window.location.assign(n.href)},sourceContextResolver:h,styleNonce:z,position:e.position}),x=m.resolvePage?{origin:i.origin,resolvePage:e=>m.resolvePage(e)}:null,r.remove(),b===r&&(b=null),v=!0,window.dispatchEvent(new CustomEvent(`visual-review:ready`,{detail:_})),_):null}function X(e,t){if(!h(e))return;let n=I.get(t);if(!n)return;let[r,i,a]=n;O(r,i,a),R.get(i)===a&&R.delete(i),J(r,i,k,a)}function Z(e,t){return!r&&i===e&&a===t&&!t.signal.aborted}function Q(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)}}function u(e){return[`현재 Origin이 Visual Review 프로젝트에 등록되어 있지 않아 시작할 수 없습니다.`,``,`현재 Origin:`,e,``,`프로젝트 설정에 위 값을 그대로 추가한 다음 초대 링크를 다시 여세요.`,`프로토콜, 호스트 이름, 포트까지 정확히 일치해야 합니다.`].join(`
|
|
3
|
-
`)}function d(e,t){return JSON.stringify([L(e).buildId,t.pathname,t.search])}async function f(e){let{createHostedReviewRuntime:t}=await import(`./hosted-runtime-BKZERnAW.js`);return t({serviceUrl:e})}async function p(e){return I(import(`./src-CtuDVE7s.js`),e,a,`리뷰 위젯을 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`)}async function ee(e,t,n,r){let i=L(e),{createGeneratedSourceContextResolver:o}=await I(import(`./generated-source-context-D59o5CKS.js`),n,a,`리뷰 소스 정보를 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`);return o({build:i})}function m(e,t){return e instanceof Error&&`code`in e&&e.code===t}function h(e){let t=_(e);return typeof t==`string`&&/^INVITATION_(?:EXPIRED|NOT_FOUND|REVOKED)$/.test(t)}function g(e){return h(e)||_(e)===`UNSUPPORTED_SERVICE_VERSION`}function _(e){return e instanceof Error&&`code`in e?e.code:void 0}const v=new WeakMap;function y(e,t){let n=v.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),b(e)},patchedReplaceState:function(t,n,r){i.call(this,t,n,r),b(e)},popstateListener:()=>b(e),subscribers:a,suppressionDepth:0},v.set(e,n),x(t,`pushState`,n.patchedPushState),x(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),S(n.history,`pushState`,n.patchedPushState,n.originalPushStateDescriptor),S(n.history,`replaceState`,n.patchedReplaceState,n.originalReplaceStateDescriptor),v.delete(e)))}}}function b(e){let t=v.get(e);if(!t||t.suppressionDepth>0)return;let n=w(e.location);[...t.subscribers].forEach(e=>e(n))}function x(e,t,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:!0,value:n})}function S(e,t,n,r){if(Object.getOwnPropertyDescriptor(e,t)?.value===n){if(r){Object.defineProperty(e,t,r);return}delete e[t]}}function C(e,t){return`${e.origin}\n${e.pathname}\n${j(t,e.href)??``}`}function w(e){return new URL(e.href)}function te(e){return e?{invitationId:e,source:`memory`}:null}function T(e){return e?{invitationId:e.invitationId,emailToken:e.emailToken,source:`handoff`}:null}function E(e,t){return JSON.stringify([e,t])}function D(e,t,n=Date.now()){let i=E(e,t),a=r.get(i);if(a){if(a.expiresAt>n)return a;clearTimeout(a.timeout),r.delete(i)}}function ne(e,t,n,a,o=Date.now()){k(o);let s=E(e,t),c=r.get(s);for(c&&(clearTimeout(c.timeout),r.delete(s));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 l=o+i,u=setTimeout(()=>{r.get(s)?.expiresAt===l&&r.delete(s)},i);r.set(s,{invitationId:n,emailToken:a,expiresAt:l,timeout:u})}function O(e,t,n){let i=E(e,t),a=r.get(i);a?.invitationId===n&&(clearTimeout(a.timeout),r.delete(i))}function k(e){for(let[t,n]of r)n.expiresAt>e||(clearTimeout(n.timeout),r.delete(t))}function A(e,t,n,r,i){let a=j(t,n.href);if(a)return{invitationId:a,emailToken:M(n.href)??void 0,source:`url`};let o=q(r,Y(e,n.origin));return o?{invitationId:o,source:`storage`}:i&&X(n.hostname)?{invitationId:`local-preview`,source:`local-preview`}:null}function j(e,t){let n=new URL(t),r=N(n.hash);return(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()||null}function M(e){let t=(N(new URL(e).hash)?.get(`visual-review-token`))?.trim();return t&&/^[A-Za-z0-9_-]{43}$/u.test(t)?t:null}function N(e){let t=e.startsWith(`#`)?e.slice(1):e,n=t.startsWith(`?`)?t.slice(1):t;return n.includes(`=`)?new URLSearchParams(n):null}function P(e){let t=new URL(window.location.href),n=new Set([e,`visual-review`,`agency-review`,`agency-review-invite`,`visual-review-token`]),r=!1;n.forEach(e=>{t.searchParams.has(e)&&(t.searchParams.delete(e),r=!0)});let i=N(t.hash);if(i){n.forEach(e=>{i.has(e)&&(i.delete(e),r=!0)});let e=i.toString();t.hash=e?`#${e}`:``}r&&window.history.replaceState(window.history.state,``,`${t.pathname}${t.search}${t.hash}`)}function F(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 I(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 re(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 L(e){let t=document.querySelector(`meta[name="visual-review-build"]`),n=document.querySelector(`meta[name="visual-review-commit"]`),r=K(B()),i=K(V());return{buildId:G(e?.buildId)??W(t)??r??`unversioned`,gitCommit:H(e,n,i),generatedAt:e?.generatedAt,mode:e?.mode??z(R())??(X(window.location.hostname)?`development`:`production`)}}function R(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_MODE}catch{return}}function z(e){return e===`development`||e===`preview`||e===`production`?e:void 0}function B(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_ID}catch{return}}function V(){try{return process.env.VISUAL_REVIEW_PUBLIC_GIT_COMMIT}catch{return}}function H(e,t,n){return e?.gitCommit===null?null:typeof e?.gitCommit==`string`?U(e.gitCommit):U(t?.content)??U(n)}function U(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 W(e){return K(e?.content)}function G(e){let t=typeof e==`string`?e.trim():``;return t.length>0?t:null}function K(e){return typeof e==`string`&&e.length>0?e:null}function ie(e,t,n,r){try{r?.setItem(Y(e,n.origin),t)}catch{}}function q(e,t){try{return e?.getItem(t)??null}catch{return null}}function ae(e){try{return e.localStorage}catch{return null}}function J(e,t,n,r){try{if(!n)return;let i=Y(e,t),a=n.getItem(i);if(a===null||r!==void 0&&a!==r)return;n.removeItem(i)}catch{}}function Y(e,t){return`visual-review:${e}:${t}:invitation`}function X(e){return e===`localhost`||e===`127.0.0.1`||e.endsWith(`.test`)||e.endsWith(`.local`)}function oe(e,t){let n=e instanceof Error?e.message:String(e),r=Error(Z(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:Z(n,t)}),typeof i==`number`&&Number.isFinite(i)&&Object.defineProperty(r,"status",{configurable:!0,enumerable:!0,value:i})}return r}function Z(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 se(e,t){if(e!==void 0)return $(e);let n=t.currentScript,r=n?Q(n):void 0;if(r)return r;try{for(let e of t.querySelectorAll(`script[nonce],style[nonce]`)){let t=Q(e);if(t)return t}}catch{}}function Q(e){let t=`nonce`in e?e.nonce:void 0;return typeof t==`string`?$(t):void 0}function $(e){return e.trim()||void 0}export{e as n,t as r,s as t};
|