@01.works/visual-review 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -8
- package/dist/generated-source-context-C6kocvPg.js +1 -0
- package/dist/{hosted-runtime-CIvL-1-W.js → hosted-runtime-1mdUKkOV.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{install-CyJ52cJi.js → install-C-4G_vDp.js} +1 -1
- package/dist/next-config.js +16 -9
- package/dist/react.js +1 -1
- package/dist/{source-index-BdWeiNHZ.js → source-index-o5fwJzns.js} +3 -1
- package/dist/{source-instrumentation-transform-BwKYKlp0.js → source-instrumentation-transform-Cx8SIIWh.js} +10 -3
- package/dist/source-loader.js +5 -2
- package/dist/vite.js +13 -6
- package/package.json +1 -1
- package/dist/generated-source-context-9dbnOHdW.js +0 -1
package/README.md
CHANGED
|
@@ -56,12 +56,20 @@ export default defineConfig({
|
|
|
56
56
|
});
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Vite와 Next.js
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
`
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
Vite와 Next.js build는 upload token이 없어도 JSX element에
|
|
60
|
+
`data-review-source="src/App.tsx:42:7"`를 기본으로 심습니다. 리뷰어의 코멘트는 그대로
|
|
61
|
+
파일 위치를 가지고 저장되며, index를 내려받거나 symbolication을 거치지 않습니다.
|
|
62
|
+
Vite dev server(`vite dev`)도 같은 값을 내보내므로 staging preview가 dev server여도
|
|
63
|
+
source 위치가 남습니다. 공개 산출물에 marker salt와 upload token은 넣지 않습니다.
|
|
64
|
+
|
|
65
|
+
`embedSourcePath: false`는 이 경로를 감추고 per-build HMAC opaque marker와
|
|
66
|
+
generated-asset locator index를 대신 씁니다. 이 형태는 owner-only symbolication을
|
|
67
|
+
거쳐야 파일 위치가 되고, index를 쓰는 production build에서만 동작합니다. 파일 경로를
|
|
68
|
+
읽히면 안 되는 리뷰어에게만 쓰세요.
|
|
69
|
+
|
|
70
|
+
`sourceMetadata: false`는 두 형태를 모두 끄고 공개 build identity만 남깁니다. 이
|
|
71
|
+
설정들은 private source-map upload를 활성화하거나 비활성화하지 않으며 upload는 아래
|
|
72
|
+
`sourceMaps`/token gate를 그대로 따릅니다.
|
|
65
73
|
|
|
66
74
|
CI에 project-scoped `VISUAL_REVIEW_SOURCE_MAP_TOKEN`을 설정하면 같은 plugin이
|
|
67
75
|
browser build에 hidden source map을 만들고 기본 서비스
|
|
@@ -109,8 +117,9 @@ export function App() {
|
|
|
109
117
|
지원 검증 범위는 Next.js 15.5와 16입니다. `/next` entry가 client boundary를
|
|
110
118
|
포함하므로 server layout에서 import할 수 있습니다. `next.config` wrapper는
|
|
111
119
|
object와 sync/async config factory를 보존합니다. 기존 webpack/Turbopack 설정을
|
|
112
|
-
유지하면서 실제 CLI가 선택한 bundler에
|
|
113
|
-
build identity로는 같은 공개 provenance 두 값만 추가합니다.
|
|
120
|
+
유지하면서 실제 CLI가 선택한 bundler에 source metadata loader를 추가하고,
|
|
121
|
+
build identity로는 같은 공개 provenance 두 값만 추가합니다. Webpack과 Turbopack 모두
|
|
122
|
+
Vite와 같은 `embedSourcePath` 기본값을 따릅니다.
|
|
114
123
|
Next가 config를 다시 평가하는 compiler worker에는 main build가 확정한 공개
|
|
115
124
|
`buildId`/`gitCommit`만 process-local record로 전달합니다. 이 record는 엄격히
|
|
116
125
|
검증되며 source-map token과 private marker salt를 포함하거나 산출물에 내보내지
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./generated-frame-CkUKpj5U.js";function t(e){let t=new Map,i=e.sourceIndexBaseUrl;return{unavailableProvenance:()=>p(e,`unavailable`),async resolve(a,o){let s=o?.signal;m(s);let c=a.closest(`[data-review-source]`),l=a.closest(`[data-visual-review-source]`),u=c?n(c):l?await r(l,t,s,i):null;return m(s),{source:u,componentStack:u?[u]:[],provenance:p(e,u?`fallback`:`unavailable`)}}}}function n(e){let t=e.getAttribute(`data-review-source`)?.trim();if(!t)return null;let n=/^(.*?)(?::(\d+))?(?::(\d+))?$/u.exec(t),r=n?.[1]?.trim();return r?{filePath:r,lineNumber:n?.[2]?Number(n[2]):null,columnNumber:n?.[3]?Number(n[3]):null,componentName:e.getAttribute(`data-review-component`)?.trim()||null,origin:`app`}:null}async function r(e,t,n,r){let a=e.getAttribute(`data-visual-review-source`),s=e.getAttribute(`data-visual-review-source-index`);if(!a||!/^vr1_[0-9a-f]{32}$/u.test(a)||!s)return null;let l=i(s,e.ownerDocument,r);if(!l||typeof globalThis.fetch!=`function`)return null;let u=t.get(l);if(!u){if(t.size>=y)return null;u=o(l),t.set(l,u)}let f;try{f=await h(u,n)}catch{return null}let p=c(f,a);return p?d(p):null}function i(e,t,n){if(e.length>2048||e.trim()!==e||e.includes(`\\`)||/[\u0000-\u001f\u007f\u202a-\u202e\u2066-\u2069]/u.test(e))return null;try{let r=new URL(e,n??t.baseURI);return r.origin!==t.location.origin||r.username||r.password||r.search||r.hash||!a(r.pathname)?null:r.href}catch{return null}}function a(e){return S.test(e)||C.test(e)}async function o(e){let t=await globalThis.fetch(e,{cache:`force-cache`,credentials:`same-origin`});if(!t.ok)throw Error(`Visual Review source index returned HTTP ${t.status}`);let n=t.headers.get(`content-length`),r=n===null?null:Number(n);if(r!==null&&(!Number.isSafeInteger(r)||r<0||r>v))throw Error(`Visual Review source index exceeds 8 MiB`);let i=await s(t);return JSON.parse(i)}async function s(e){let t=e.body?.getReader();if(!t)return``;let n=new TextDecoder(`utf-8`,{fatal:!0}),r=[],i=0;try{for(;;){let{done:e,value:a}=await t.read();if(e)break;if(i+=a.byteLength,i>v)throw await t.cancel(`Visual Review source index exceeds 8 MiB`),Error(`Visual Review source index exceeds 8 MiB`);r.push(n.decode(a,{stream:!0}))}return r.push(n.decode()),r.join(``)}finally{t.releaseLock()}}function c(t,n){if(!u(t)||t.schemaVersion!==1||!u(t.entries))return;let r=t.entries[n];if(!(!Array.isArray(r)||r.length===0||r.length>b))for(let t of r){if(!u(t)||!l(t.runtime))continue;let n=e(t.assetPath),r=f(t.line1,1,g),i=f(t.column0,0,_);if(!(!n||r===null||i===null))return{assetPath:n,line1:r,column0:i,runtime:t.runtime}}}function l(e){return e===`browser`||e===`server-node`||e===`server-edge`}function u(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function d(e){return{filePath:e.assetPath,lineNumber:e.line1,columnNumber:e.column0+1,componentName:null,origin:`generated`,generated:e}}function f(e,t,n){return typeof e==`number`&&Number.isSafeInteger(e)&&e>=t&&e<=n?e:null}function p(e,t){return{provider:`embedded`,build:e.build,resolvedAt:e.now?.()??Date.now(),sourceMapStatus:t}}function m(e){if(e?.aborted)throw e.reason??Error(`Source context resolution aborted`)}function h(e,t){return t?t.aborted?Promise.reject(t.reason??Error(`Source context resolution aborted`)):new Promise((n,r)=>{let i=()=>r(t.reason??Error(`Source context resolution aborted`));t.addEventListener(`abort`,i,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})}):e}const g=1e7,_=1e7,v=8*1024*1024,y=16,b=64,x=`visual-review-sources-[0-9a-f]{16}\\.json`,S=RegExp(`^/(?:[^/]+/)*\\.visual-review/${x}$`,`u`),C=RegExp(`^/(?:[^/]+/)*_next/static/${x}$`,`u`);export{t as createGeneratedSourceContextResolver};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as e}from"./install-CyJ52cJi.js";import{t}from"./generated-frame-CkUKpj5U.js";import{i as n,init as r}from"@instantdb/core";const i=n.schema({entities:{$users:n.entity({email:n.string().unique().indexed()}),projects:n.entity({name:n.string(),slug:n.string().unique().indexed(),allowedOrigin: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()}),sourceMapUploadTokens:n.entity({projectId:n.string().indexed(),tokenHash:n.string().unique().indexed(),tokenPrefix:n.string(),scope:n.string(),expiresAt:n.number().indexed(),revokedAt:n.number().optional(),createdAt:n.number().indexed()}),sourceMapReleases:n.entity({projectId:n.string().indexed(),buildId:n.string().indexed(),gitCommit:n.string().optional(),mode:n.string(),framework:n.string(),frameworkVersion:n.string().optional(),status:n.string().indexed(),expiresAt:n.number().indexed(),createdAt:n.number().indexed(),updatedAt:n.number(),completedAt:n.number().optional()}),sourceMapArtifacts:n.entity({releaseId:n.string().indexed(),generatedPath:n.string().indexed(),runtime:n.string().indexed(),objectKey:n.string().unique().indexed(),mapSha256:n.string().indexed(),generatedSha256:n.string(),debugId:n.string().optional(),byteSize:n.number(),createdAt: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()}),comments:n.entity({pageId:n.string().indexed(),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(),status:n.string().indexed(),workflowRevision:n.number(),createdAt:n.number().indexed(),updatedAt:n.number().indexed(),resolvedAt:n.number().optional(),resolvedById:n.string().optional()}),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`}},pageCurrentBuild:{forward:{on:`reviewPageBuilds`,has:`one`,label:`page`,required:!0,onDelete:`cascade`},reverse:{on:`reviewPages`,has:`one`,label:`currentBuild`}},projectSourceMapUploadTokens:{forward:{on:`projects`,has:`many`,label:`uploadTokens`},reverse:{on:`sourceMapUploadTokens`,has:`one`,label:`project`,required:!0,onDelete:`cascade`}},projectSourceMapReleases:{forward:{on:`projects`,has:`many`,label:`sourceMapReleases`},reverse:{on:`sourceMapReleases`,has:`one`,label:`project`,required:!0,onDelete:`cascade`}},sourceMapReleaseArtifacts:{forward:{on:`sourceMapReleases`,has:`many`,label:`artifacts`},reverse:{on:`sourceMapArtifacts`,has:`one`,label:`release`,required:!0,onDelete:`cascade`}},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:`one`,label:`activeReviewInvitation`}},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`}},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(),cursorX:n.number().optional(),cursorY:n.number().optional(),viewportWidth:n.number().optional(),viewportHeight:n.number().optional()})}}}),a=new Uint8Array([107,167,184,17,157,173,17,209,128,180,0,192,79,212,48,200]);function o(e,t,n){return u(e,n),`${e}:${t}:${n}`}async function s(e,t,n){return l(o(e,t,n))}async function c(e){if(!e.trim())throw Error(`Comment ID is required for source context`);return l(`${e}:source-context`)}async function l(e){let t=globalThis.crypto?.subtle;if(!t)throw Error(`Web Crypto is required to persist review capture context`);let n=new TextEncoder().encode(`01works.visual-review/v1/${e}`),r=new Uint8Array(a.length+n.length);r.set(a),r.set(n,a.length);let i=new Uint8Array(await t.digest(`SHA-1`,r)).slice(0,16);i[6]=i[6]&15|80,i[8]=i[8]&63|128;let o=[...i].map(e=>e.toString(16).padStart(2,`0`)).join(``);return`${o.slice(0,8)}-${o.slice(8,12)}-${o.slice(12,16)}-${o.slice(16,20)}-${o.slice(20)}`}function u(e,t){if(!e.trim())throw Error(`Comment ID is required for capture context`);if(!Number.isSafeInteger(t)||t<0)throw Error(`Capture child ordinal must be a non-negative integer`)}const d=131072,f=32768,p=4096,m=1e3;var h=class extends Error{constructor(e,t){super(e,t),this.name=`InstantCaptureIntegrityError`}};function g(e){let t=re(e,`comment target`,!0),n={kind:t.kind,anchor:ue(t.anchor),region:pe(t.region),elements:t.elements.map(e=>({selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,rect:pe(e.rect),source:null,componentStack:[]})),pageUrl:t.pageUrl,pageTitle:t.pageTitle,capturedAt:t.capturedAt},r={elements:t.elements.map(e=>({selector:e.selector,source:e.source?me(e.source):null,componentStack:e.componentStack.map(me)})),...t.sourceProvenance?{sourceProvenance:he(t.sourceProvenance)}:{}};M(n,d,`Public target`);let i=xe(r,65536,`Source context`);return{publicTarget:n,commentFields:y(n),targetElements:n.elements.map(b),sourceContextJson:i}}function ee(e,t,n){let r=T(e,n),i={selector:E(r.anchorSelector,`${n} anchor selector`,p),offsetX:A(r.anchorOffsetX,`${n} anchor offsetX`),offsetY:A(r.anchorOffsetY,`${n} anchor offsetY`),viewportX:A(r.anchorViewportX,`${n} anchor viewportX`),viewportY:A(r.anchorViewportY,`${n} anchor viewportY`)},a=x({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:fe({origin:D(r.targetPageOrigin,`${n} page origin`,1024),pathname:D(r.targetPagePathname,`${n} page pathname`,4096),search:E(r.targetPageSearch,`${n} page search`,1024),hash:E(r.targetPageHash,`${n} page hash`,1024)}),pageTitle:r.targetPageTitle,capturedAt:r.targetCapturedAt},n),o=te(t,`${n} elements`),s=a;for(let e of o)try{s=x({...a,elements:[...s.elements,e]},n)}catch{}return s}function _(e){let t=ne(e);return t?Object.entries(t).map(([e,t],n)=>typeof t==`string`?{ordinal:n,key:e,valueType:`string`,stringValue:t}:typeof t==`number`?{ordinal:n,key:e,valueType:`number`,numberValue:t}:typeof t==`boolean`?{ordinal:n,key:e,valueType:`boolean`,booleanValue:t}:{ordinal:n,key:e,valueType:`null`}):[]}function v(e){if(!Array.isArray(e)||e.length===0)return;let t=[...e].map(e=>{try{let t=T(e,`Comment scope entry`);return{row:t,ordinal:k(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=D(e.key,`Comment scope key`,256);if(Object.hasOwn(n,t))continue;switch(e.valueType){case`string`:n[t]=E(e.stringValue,`Comment scope ${t}`,m);break;case`number`:n[t]=O(e.numberValue,`Comment scope ${t}`);break;case`boolean`:if(typeof e.booleanValue!=`boolean`)throw N(`Comment scope ${t} is invalid`);n[t]=e.booleanValue;break;case`null`:n[t]=null;break;default:throw N(`Comment scope ${t} is invalid`)}}catch{}}if(Object.keys(n).length!==0)try{return M(n,f,`Comment scope`),n}catch{return}}function y(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:de(t.pathname),targetPageSearch:t.search.slice(1),targetPageHash:t.hash.slice(1),targetPageTitle:e.pageTitle,targetCapturedAt:e.capturedAt}}function b(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 te(e,t){if(!Array.isArray(e)||e.length===0)return[];let n=[...e].map(e=>{try{let n=T(e,t);return{row:n,ordinal:k(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(ie({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 x(e,t){return re(e,t,!1)}function S(e,t=`Comment body`){return D(e,t,2e4)}function C(e,t=`Comment body`){let n=S(e,t);for(let e of n)if(e.trim())return e;throw N(`${t} is empty`)}function ne(e){if(e==null)return;let t=T(e,`Comment scope`);if(Object.keys(t).length>20)throw N(`Comment scope has too many fields`);let n={};for(let[e,r]of Object.entries(t)){if(!e.trim()||e.length>256)throw N(`Comment scope has an invalid key`);if(typeof r==`string`){if(r.length>m)throw N(`Comment scope ${e} is too long`);n[e]=r}else if(typeof r==`number`)n[e]=O(r,`Comment scope ${e}`);else if(typeof r==`boolean`||r===null)n[e]=r;else throw N(`Comment scope ${e} is invalid`)}return M(n,f,`Comment scope`),n}function re(e,t,n){let r=w(e,t,[`kind`,`anchor`,`region`,`elements`,`pageUrl`,`pageTitle`,`capturedAt`,`sourceProvenance`],[`sourceProvenance`]),i=r.kind;if(i!==`element`&&i!==`region`&&i!==`viewport`)throw N(`${t} kind is invalid`);let a=ge(r.elements,`${t} elements`);if(a.length>8)throw N(`${t} contains too many elements`);if(!n&&r.sourceProvenance!=null)throw N(`${t} exposes source provenance`);let o=D(r.pageUrl,`${t} pageUrl`,8192);be(o,`${t} pageUrl`);let s={kind:i,anchor:ae(r.anchor,`${t} anchor`),region:oe(r.region,`${t} region`),elements:a.map((e,r)=>ie(e,`${t} elements[${r}]`,n)),pageUrl:o,pageTitle:E(r.pageTitle,`${t} pageTitle`,m),capturedAt:j(r.capturedAt,`${t} capturedAt`),...n&&r.sourceProvenance!=null?{sourceProvenance:le(r.sourceProvenance,`${t} provenance`)}:{}};return M(s,n?196608:d,t),s}function ie(e,t,n){let r=w(e,t,[`selector`,`tagName`,`textPreview`,`rect`,`source`,`componentStack`]),i=ge(r.componentStack,`${t} componentStack`);if(i.length>32)throw N(`${t} componentStack is too large`);if(!n&&(r.source!=null||i.length>0))throw N(`${t} exposes source metadata`);return{selector:D(r.selector,`${t} selector`,p),tagName:D(r.tagName,`${t} tagName`,128),textPreview:E(r.textPreview,`${t} textPreview`,m),rect:oe(r.rect,`${t} rect`),source:n&&r.source!=null?se(r.source,`${t} source`):null,componentStack:n?i.map((e,n)=>se(e,`${t} stack[${n}]`)):[]}}function ae(e,t){let n=w(e,t,[`selector`,`offsetX`,`offsetY`,`viewportX`,`viewportY`]);return{selector:E(n.selector,`${t} selector`,p),offsetX:A(n.offsetX,`${t} offsetX`),offsetY:A(n.offsetY,`${t} offsetY`),viewportX:A(n.viewportX,`${t} viewportX`),viewportY:A(n.viewportY,`${t} viewportY`)}}function oe(e,t){let n=w(e,t,[`pageX`,`pageY`,`width`,`height`,`viewportX`,`viewportY`,`viewportWidth`,`viewportHeight`]),r={pageX:O(n.pageX,`${t} pageX`),pageY:O(n.pageY,`${t} pageY`),width:O(n.width,`${t} width`),height:O(n.height,`${t} height`),viewportX:O(n.viewportX,`${t} viewportX`),viewportY:O(n.viewportY,`${t} viewportY`),viewportWidth:O(n.viewportWidth,`${t} viewportWidth`),viewportHeight:O(n.viewportHeight,`${t} viewportHeight`)};if(r.width<0||r.height<0||r.viewportWidth<0||r.viewportHeight<0)throw N(`${t} has a negative dimension`);return r}function se(e,t){let n=w(e,t,[`filePath`,`lineNumber`,`columnNumber`,`componentName`,`origin`,`generated`],[`generated`]),r=n.origin;if(r!==`app`&&r!==`shared-ui`&&r!==`dependency`&&r!==`generated`&&r!==`unknown`)throw N(`${t} origin is invalid`);return{filePath:D(n.filePath,`${t} filePath`,p),lineNumber:ye(n.lineNumber,`${t} lineNumber`),columnNumber:ye(n.columnNumber,`${t} columnNumber`),componentName:n.componentName==null?null:D(n.componentName,`${t} componentName`,512),origin:r,...n.generated===void 0?{}:{generated:ce(n.generated,`${t} generated`)}}}function ce(e,n){let r=w(e,n,[`assetPath`,`line1`,`column0`,`runtime`,`debugId`],[`debugId`]),i=t(r.assetPath);if(!i)throw N(`${n} assetPath is invalid`);let a=r.runtime;if(a!==`browser`&&a!==`server-node`&&a!==`server-edge`&&a!==`unknown`)throw N(`${n} runtime is invalid`);return{assetPath:i,line1:k(r.line1,`${n} line1`,1,1e7),column0:k(r.column0,`${n} column0`,0,1e7),runtime:a,...r.debugId===void 0?{}:{debugId:ve(r.debugId,`${n} debugId`)}}}function le(e,t){let n=w(e,t,[`provider`,`build`,`resolvedAt`,`sourceMapStatus`]),r=n.provider;if(r!==`react-grab`&&r!==`embedded`&&r!==`custom`)throw N(`${t} provider is invalid`);let i=n.sourceMapStatus;if(i!==`resolved`&&i!==`fallback`&&i!==`unavailable`)throw N(`${t} sourceMapStatus is invalid`);let a=w(n.build,`${t} build`,[`buildId`,`gitCommit`,`generatedAt`,`mode`],[`generatedAt`]),o=a.mode;if(o!==`development`&&o!==`preview`&&o!==`production`)throw N(`${t} build mode is invalid`);return{provider:r,build:{buildId:D(a.buildId,`${t} buildId`,512),gitCommit:a.gitCommit==null?null:D(a.gitCommit,`${t} gitCommit`,256),...a.generatedAt==null?{}:{generatedAt:j(a.generatedAt,`${t} generatedAt`)},mode:o},resolvedAt:j(n.resolvedAt,`${t} resolvedAt`),sourceMapStatus:i}}function ue(e){return{...e}}function de(e){return e.replace(/\/+$/,``)||`/`}function fe(e){return`${e.origin}${e.pathname}${e.search?`?${e.search}`:``}${e.hash?`#${e.hash}`:``}`}function pe(e){return{...e}}function me(e){return{...e,...e.generated?{generated:{...e.generated}}:{}}}function he(e){return{...e,build:{...e.build}}}function w(e,t,n,r=[]){let i=T(e,t);if(Object.keys(i).some(e=>!n.includes(e)))throw N(`${t} contains unknown fields`);for(let e of n)if(!r.includes(e)&&!Object.hasOwn(i,e))throw N(`${t} is missing ${e}`);return i}function T(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw N(`${t} is missing or invalid`);return e}function ge(e,t){if(!Array.isArray(e))throw N(`${t} is missing or invalid`);return e}function E(e,t,n){if(typeof e!=`string`||_e(e,n)>n)throw N(`${t} is invalid or too long`);return e}function _e(e,t){let n=0;for(let r of e)if(n+=1,n>t)return n;return n}function D(e,t,n){let r=E(e,t,n);if(!r.trim())throw N(`${t} is empty`);return r}function O(e,t){if(typeof e!=`number`||!Number.isFinite(e))throw N(`${t} is invalid`);return e}function k(e,t,n,r){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<n||e>r)throw N(`${t} is invalid`);return e}function ve(e,t){let n=D(e,t,256);if(!/^[A-Za-z0-9._:-]+$/u.test(n))throw N(`${t} is invalid`);return n}function A(e,t){let n=O(e,t);if(n<0||n>1)throw N(`${t} is outside 0..1`);return n}function j(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw N(`${t} is invalid`);return e}function ye(e,t){if(e===null)return null;if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0)throw N(`${t} is invalid`);return e}function be(e,t){let n;try{n=new URL(e)}catch(e){throw N(`${t} is invalid`,e)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw N(`${t} must use HTTP or HTTPS`)}function M(e,t,n){xe(e,t,n)}function xe(e,t,n){let r;try{r=JSON.stringify(e)}catch(e){throw N(`${n} cannot be serialized`,e)}if(r.length>t)throw N(`${n} is too large`);return r}function N(e,t){return new h(e,{cause:t instanceof Error?t:void 0})}function Se(e){if(!e.trim())throw Error(`InstantDB app ID is required`);return r({appId:e,schema:i})}var Ce=class{db;session;#e;constructor(e,t,n={}){this.db=e,this.session=t,this.#e=n.commentTransport}async getSnapshot(e){let{data:t}=await this.db.queryOnce(we(e,this.session.authUserId));return Te(e,t.comments,t.replies)}subscribe(e,t,n){return this.db.subscribeQuery(we(e,this.session.authUserId),r=>{if(r.error){n?.(Me(r.error));return}if(r.data)try{t(Te(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=S(n.body).trim(),i=C(r),a=L(n.createdAt,`Comment createdAt`),l=L(n.updatedAt,`Comment updatedAt`);if(l<a)throw new h(`Comment updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new h(`Comment edits must go through the review service`);if(n.status!==`open`||n.resolvedAt!==void 0||n.resolvedById!==void 0)throw new h(`New comments must start open`);let u=g(n.target);if(!ke(n.anchor,u.publicTarget.anchor))throw new h(`Comment anchor does not match its target`);if(this.#e){await this.#e.createComment({pageId:e,commentId:n.id,body:r,target:n.target,...n.scope===void 0?{}:{scope:n.scope}});return}let d=_(n.scope),f=await Promise.all(u.targetElements.map(async e=>({element:e,id:await s(n.id,`element`,e.ordinal),slotKey:o(n.id,`element`,e.ordinal)}))),p=await Promise.all(d.map(async e=>({entry:e,id:await s(n.id,`scope`,e.ordinal),slotKey:o(n.id,`scope`,e.ordinal)}))),m=await c(n.id);await this.db.transact([this.db.tx.comments[n.id].update({pageId:e,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:r,bodyContentMarker:i,...u.commentFields,status:n.status,workflowRevision:0,createdAt:a,updatedAt:l}).link({page:e,author:this.session.reviewerId}),...f.map(({element:e,id:t,slotKey:r})=>this.db.tx.commentTargetElements[t].update({commentId:n.id,slotKey:r,authorAuthUserId:this.session.authUserId,...e}).link({comment:n.id})),...p.map(({entry:e,id:t,slotKey:r})=>this.db.tx.commentScopeEntries[t].update({commentId:n.id,slotKey:r,authorAuthUserId:this.session.authUserId,...e}).link({comment:n.id})),this.db.tx.commentSourceContexts[m].update({commentId:n.id,pageId:e,authorAuthUserId:this.session.authUserId,contextJson:u.sourceContextJson,createdAt:a}).link({comment:n.id,page:e,author:this.session.reviewerId})]);return}case`comment.delete`:throw new h(`Comment deletion must go through the review service`);case`reply.upsert`:{let n=t.reply;if(n.authorId!==this.session.reviewerId)throw Error(`Reply author mismatch`);let r=S(n.body,`Reply body`).trim(),i=C(r,`Reply body`),a=L(n.createdAt,`Reply createdAt`),o=L(n.updatedAt,`Reply updatedAt`);if(o<a)throw new h(`Reply updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new h(`Reply edits must go through the review service`);if(this.#e){await this.#e.createReply({commentId:n.commentId,replyId:n.id,body:r});return}await this.db.transact(this.db.tx.replies[n.id].update({pageId:e,commentId:n.commentId,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:r,bodyContentMarker:i,createdAt:a,updatedAt:o}).link({comment:n.commentId,author:this.session.reviewerId}));return}case`reply.delete`:throw new h(`Reply deletion must go through the review service`)}}};function we(e,t){return{comments:{$:{where:{pageId:e},order:{createdAt:`asc`}},targetElements:{},scopeEntries:{}},replies:{$:{where:{pageId:e},order:{createdAt:`asc`}}},$users:{$:{where:{id:t}},activeReviewInvitation:{project:{}}}}}function Te(e,t,n){let r=t.map(t=>Ee(t,e));je(r,`comment`);let i=new Set(r.map(({id:e})=>e)),a=n.map(t=>De(t,e));je(a,`reply`);for(let e of a)if(!i.has(e.commentId))throw new h(`Reply ${e.id} references a comment outside the page snapshot`);return{pageId:e,comments:r,replies:a}}function Ee(e,t){let n=P(e,`comment`),r=F(n.id,`comment id`);if(F(n.pageId,`comment ${r} pageId`)!==t)throw new h(`Comment ${r} escaped its page scope`);F(n.authorAuthUserId,`comment ${r} authorAuthUserId`);let i=!(Object.hasOwn(n,`anchor`)&&Object.hasOwn(n,`target`)),a=i?ee(n,n.targetElements,`comment ${r} target`):x(n.target,`comment ${r} target`),o=i?{...a.anchor}:Oe(n.anchor,`comment ${r} anchor`);if(!ke(o,a.anchor))throw new h(`Comment ${r} has inconsistent anchors`);let s=n.status;if(s!==`open`&&s!==`resolved`)throw new h(`Comment ${r} has an invalid status`);let c=L(n.createdAt,`comment ${r} createdAt`),l=L(n.updatedAt,`comment ${r} updatedAt`);if(l<c)throw new h(`Comment ${r} updatedAt precedes createdAt`);let u=Ie(n.resolvedAt,`comment ${r} resolvedAt`),d=Le(n.resolvedById,`comment ${r} resolvedById`);if(s===`open`&&(u!==void 0||d!==void 0))throw new h(`Open comment ${r} contains resolution metadata`);if(s===`resolved`&&(u===void 0||d===void 0||u!==l))throw new h(`Resolved comment ${r} has invalid workflow metadata`);return{id:r,pageId:t,authorId:F(n.authorId,`comment ${r} authorId`),authorName:F(n.authorName,`comment ${r} authorName`),body:S(n.body,`comment ${r} body`),anchor:o,target:a,...i?Ae(v(n.scopeEntries)):n.scope==null?{}:{scope:ne(n.scope)},status:s,workflowRevision:Fe(n.workflowRevision,`comment ${r} workflowRevision`),createdAt:c,updatedAt:l,...u===void 0?{}:{resolvedAt:u},...d===void 0?{}:{resolvedById:d}}}function De(e,t){let n=P(e,`reply`),r=F(n.id,`reply id`);if(F(n.pageId,`reply ${r} pageId`)!==t)throw new h(`Reply ${r} escaped its page scope`);F(n.authorAuthUserId,`reply ${r} authorAuthUserId`);let i=L(n.createdAt,`reply ${r} createdAt`),a=L(n.updatedAt,`reply ${r} updatedAt`);if(a<i)throw new h(`Reply ${r} updatedAt precedes createdAt`);return{id:r,commentId:F(n.commentId,`reply ${r} commentId`),authorId:F(n.authorId,`reply ${r} authorId`),authorName:F(n.authorName,`reply ${r} authorName`),body:S(n.body,`reply ${r} body`),createdAt:i,updatedAt:a}}function Oe(e,t){let n=P(e,t);if(Object.keys(n).length!==5||!Object.hasOwn(n,`selector`)||!Object.hasOwn(n,`offsetX`)||!Object.hasOwn(n,`offsetY`)||!Object.hasOwn(n,`viewportX`)||!Object.hasOwn(n,`viewportY`))throw new h(`${t} has invalid fields`);return{selector:Pe(n.selector,`${t} selector`),offsetX:I(n.offsetX,`${t} offsetX`),offsetY:I(n.offsetY,`${t} offsetY`),viewportX:I(n.viewportX,`${t} viewportX`),viewportY:I(n.viewportY,`${t} viewportY`)}}function ke(e,t){return e.selector===t.selector&&e.offsetX===t.offsetX&&e.offsetY===t.offsetY&&e.viewportX===t.viewportX&&e.viewportY===t.viewportY}function Ae(e){return e===void 0?{}:{scope:e}}function je(e,t){let n=new Set;for(let r of e){if(n.has(r.id))throw new h(`Duplicate ${t} ${r.id}`);n.add(r.id)}}function Me(e){let t=Ne(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 Ne(e){return e instanceof Error?e.message:e&&typeof e==`object`&&`message`in e?String(e.message):``}function P(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new h(`${t} is missing or invalid`);return e}function Pe(e,t){if(typeof e!=`string`)throw new h(`${t} is invalid`);return e}function F(e,t){let n=Pe(e,t);if(!n.trim())throw new h(`${t} is empty`);return n}function I(e,t){if(typeof e!=`number`||!Number.isFinite(e)||e<0||e>1)throw new h(`${t} is invalid`);return e}function L(e,t){if(!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw new h(`${t} is invalid`);return e}function Fe(e,t){if(!Number.isSafeInteger(e)||e<0)throw new h(`${t} is invalid`);return e}function Ie(e,t){return e==null?void 0:L(e,t)}function Le(e,t){return e==null?void 0:F(e,t)}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`}),Object.freeze({comments:200,replies:1e3,sourceContexts:200});var Re=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=qe(e,t.roomId),a,l,u=this.roomCredential??{id:t.roomId,expiresAt:2**53-1,refresh:async()=>void 0},d=t=>{let o=this.db.joinRoom(`visualReview`,t),s=o.subscribePresence({},e=>{if(e.error){r?.(Ye(e.error));return}i=Object.values(e.peers).map(e=>Be(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?.()},f=()=>{if(!this.roomCredential||o)return;let e=Math.max(1e3,u.expiresAt-Date.now()+250);l=setTimeout(()=>{p()},e)},p=async()=>{try{let e=await u.refresh();if(o||!e)return;u={...e,refresh:u.refresh},d(e.id),f()}catch(e){if(o)return;r?.(Ye(e)),o||(l=setTimeout(()=>{p()},5e3))}};d(u.id),f(),s.push(()=>{l&&clearTimeout(l),this.#e.delete(n),a?.()})}return t.chat&&s.push(this.db.subscribeQuery(ze(e,this.session.authUserId),t=>{if(t.error){r?.(Ye(t.error));return}if(t.data)try{a=t.data.reviewMessages.map(t=>Ve(t,e)).sort(Je),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(qe(e,t));r&&r.publishPresence({reviewerId:this.session.reviewerId,displayName:this.session.displayName,color:n.color,active:n.active,...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}})}async sendMessage(e,t){if(t.pageId!==e)throw Error(`Review message page mismatch`);if(t.authorId!==this.session.reviewerId)throw Error(`Review message author mismatch`);let n=He(t.body),r=Ue(t.pathname),i=z(t.createdAt,`Review message createdAt`),a=z(t.updatedAt,`Review message updatedAt`);if(i!==a)throw Error(`New review messages must be immutable`);await this.db.transact(this.db.tx.reviewMessages[t.id].update({pageId:e,pathname:r,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:n,bodyContentMarker:C(n,`Review message body`),createdAt:i,updatedAt:a}).link({page:e,author:this.session.reviewerId}))}};function ze(e,t){return{reviewMessages:{$:{where:{pageId:e},order:{createdAt:`asc`}}},$users:{$:{where:{id:t}},activeReviewInvitation:{project:{}}}}}function Be(e){let t=We(e.reviewerId,128),n=We(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=Ge(e.cursorX),a=Ge(e.cursorY),o=Ke(e.viewportWidth),s=Ke(e.viewportHeight);return{peerId:e.peerId,reviewerId:t,displayName:n,color:r,active:e.active,...i===void 0?{}:{cursorX:i},...a===void 0?{}:{cursorY:a},...o===void 0?{}:{viewportWidth:o},...s===void 0?{}:{viewportHeight:s}}}function Ve(e,t){let n=R(e.id,`Review message id`,128);if(R(e.pageId,`Review message pageId`,128)!==t)throw Error(`Review message page mismatch`);return{id:n,pageId:t,pathname:Ue(e.pathname),authorId:R(e.authorId,`Review message authorId`,128),authorName:R(e.authorName,`Review message authorName`,512),body:He(e.body),createdAt:z(e.createdAt,`Review message createdAt`),updatedAt:z(e.updatedAt,`Review message updatedAt`)}}function He(e){return R(e,`Review message body`,4e3)}function Ue(e){let t=R(e,`Review message pathname`,2e3);if(!t.startsWith(`/`))throw Error(`Review message pathname is invalid`);return t}function R(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 We(e,t){if(typeof e!=`string`)return null;let n=e.trim();return n&&n.length<=t?n:null}function Ge(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function Ke(e){let t=Ge(e);return t!==void 0&&t>0?t:void 0}function z(e,t){if(!Number.isSafeInteger(e)||e<0)throw Error(`${t} is invalid`);return e}function qe(e,t){return JSON.stringify([e,t])}function Je(e,t){return e.createdAt-t.createdAt||e.id.localeCompare(t.id)}function Ye(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`});const B={$default:`false`},V={$default:`false`},H=`$user.activeReviewInvitation.project.id`;function U(e){return[`auth.id != null`,`size(auth.ref('$user.activeReviewInvitation.id')) == 1`,`size(auth.ref('${H}')) == 1`,`size(auth.ref('$user.activeReviewInvitation.status')) == 1`,`size(auth.ref('$user.activeReviewInvitation.expiresAt')) == 1`,`size(auth.ref('$user.activeReviewInvitation.revokedAt')) == 0`,`auth.ref('$user.activeReviewInvitation.status')[0] == 'accepted'`,`request.time < timestamp(auth.ref('$user.activeReviewInvitation.expiresAt')[0])`,e].join(` && `)}function W(...e){return e.map(e=>`(${e})`).join(` && `)}function G(...e){return e.map(e=>`(${e})`).join(` || `)}function K(e,t){return`!has(${e}.${t}) || ${e}.${t} == null`}const Xe=`actions.data == 'create' && actions.linkedData == 'update'`,Ze=e=>`${e}.matches('[^ \\t\\n\\r\\f\\u000b\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]')`,Qe=e=>W(`${e} >= 0`,`${e} <= 253402300799999`,`${e} % 1 == 0`),$e=e=>W(Qe(e),`(request.time - timestamp(${e})).getSeconds() <= 86400`,`(request.time - timestamp(${e})).getSeconds() >= -300`);W(`actions.data == 'update' && actions.linkedData == 'create'`,G(`auth.id != null && auth.id in data.ref('project.owners.id')`,U(`auth.ref('${H}')[0] in data.ref('project.id')`))),W(Xe,G(`auth.id != null && auth.id in data.ref('page.project.owners.id')`,U(`auth.ref('${H}')[0] in data.ref('page.project.id')`)),`auth.id != null && auth.id == data.authorAuthUserId && auth.id in data.ref('author.$user.id')`,`data.pageId in data.ref('page.id')`,`data.authorId in data.ref('author.id') && data.authorAuthUserId in data.ref('author.$user.id') && data.authorName in data.ref('author.displayName')`,`data.pageId in data.ref('author.project.pages.id')`),W(Xe,`data.pageId == linkedData.id`,`auth.id != null && auth.id == data.authorAuthUserId`,`data.authorId in auth.ref('$user.reviewerMemberships.id')`,`data.authorId in linkedData.ref('project.reviewers.id')`,G(`auth.id != null && auth.id in linkedData.ref('project.owners.id')`,U(`auth.ref('${H}')[0] in linkedData.ref('project.id')`)));const et=`auth.id != null && auth.id in data.ref('comment.page.project.owners.id')`,tt=U(`auth.ref('${H}')[0] in data.ref('comment.page.project.id')`);U(`auth.ref('${H}')[0] in data.ref('comment.page.project.id')`),U(`auth.ref('${H}')[0] in data.ref('page.project.id')`);const nt=W(`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')`);W(`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`,nt),W(`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`,nt),W(`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')`),W(`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')`),W(`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')`),{...B},{...V},{...V},U(`data.id == auth.ref('${H}')[0]`),{...B},W(`isOwner`,G(W(K(`data`,`allowedOrigin`),K(`newData`,`allowedOrigin`)),`newData.allowedOrigin == data.allowedOrigin`)),{...V},{...B},W(`isOwner`,G(W(K(`data`,`autoRegistrationSlot`),K(`newData`,`autoRegistrationSlot`)),`newData.autoRegistrationSlot == data.autoRegistrationSlot`)),{...V},{...B},{...V},{...B},{...V},{...B},{...V},{...B},{...V},U(`auth.ref('${H}')[0] in data.ref('project.id')`),{...B},{...V},{...B},{...B},{...V},{...V},{...B},{...V},{...B},G(et,tt),{...B},G(et,tt),{...B},{...B},W(`data.createdAt == data.updatedAt`,$e(`data.createdAt`),`size(data.body) > 0`,`size(data.body) <= 4000`,`size(data.bodyContentMarker) == 1`,Ze(`data.bodyContentMarker`),`data.body.startsWith(data.bodyContentMarker)`,`size(data.authorName) > 0`,`size(data.authorName) <= 512`,Ze(`data.authorName`),`size(data.pathname) > 0`,`size(data.pathname) <= 2000`,`request.modifiedFields.all(field, field in ['pageId', 'pathname', 'authorId', 'authorAuthUserId', 'authorName', 'body', 'bodyContentMarker', 'createdAt', 'updatedAt', 'page', 'author'])`),{...B},{...V};var rt=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewerCommentSaveError`}};function it(e,t){let n=e.replace(/\/+$/,``),r=async(e,r)=>{let i=await t();if(!i)throw new rt(`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 rt(`NETWORK`,`리뷰 서버에 연결하지 못했습니다. 연결을 확인하고 다시 시도해 주세요.`)}if(!a.ok)throw new rt(...await at(a))};return{createComment:e=>r(`/v1/comments`,e),createReply:e=>r(`/v1/replies`,e)}}async function at(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 ot=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewBootstrapError`}};const q=new Map;function st(e,t={}){let n=e.trim();if(!n)throw Error(`InstantDB app ID is required`);return{async resolve(e){let r=(t.databaseFactory??Se)(n),i=await ut(n,r,e.authHost,e.signal,e.styleNonce);for(;;)try{await ct(t.acceptInvitation,{refreshToken:i.refresh_token,invitationId:e.invitationId,suggestedDisplayName:Ct(i.email),authHost:e.authHost,signal:e.signal,styleNonce:e.styleNonce});break}catch(t){if(!wt(t,`INVITATION_EMAIL_MISMATCH`))throw t;await gt(e.authHost,e.signal,e.styleNonce),i=await dt(n,r,i,e.authHost,e.signal,e.styleNonce)}let{data:a}=await r.queryOnce({reviewers:{$:{where:{authUserId:i.id}}},reviewPages:{$:{where:{stagingOrigin:e.location.origin}}},invitations:{}}),o=lt(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 ot(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=e.collaboration?.cursors===!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,l=c&&t.resolveCollaborationRoom?{...c,refresh:async()=>{let n=await r.getAuth();if(n?.refresh_token)return t.resolveCollaborationRoom?.({refreshToken:n.refresh_token,invitationId:e.invitationId,pageId:o.page.id,scopeId:e.collaboration.scopeId,signal:e.signal})}}:void 0;return{pageId:o.page.id,session:s,repository:new Ce(r,s,{...t.serviceUrl===void 0?{}:{commentTransport:it(t.serviceUrl,async()=>(await r.getAuth())?.refresh_token??null)}}),...e.collaboration?.cursors===!0||e.collaboration?.chat===!0?{collaborationRepository:new Re(r,s,l)}:{},...e.collaboration?.cursors===!0&&l?{collaborationRoomId:l.id}:{},allowedStagingHosts:[e.location.hostname]}}}}async function ct(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 ht(t.authHost,t.signal,t.suggestedDisplayName,t.styleNonce);await e({...n,displayName:r})}function lt(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=n.find(e=>e.projectId===i.projectId&&e.stagingOrigin===r.location.origin&&Et(e.pathname)===o);return s?{ok:!0,invitation:i,reviewer:a,page:s}:{ok:!1,code:`PAGE_NOT_FOUND`}}async function ut(e,t,n,r,i){let a=await J(r,()=>t.getAuth());if(a)return a;let o=await ft(e,r);try{return await J(r,()=>t.getAuth())||await mt(t,n,r,i)}finally{o()}}async function dt(e,t,n,r,i,a){Y(i);let o=await ft(e,i);try{let e=await J(i,()=>t.getAuth());return e&&e.id!==n.id?e:(e&&await J(i,async()=>{await t.auth.signOut()}),Y(i),await mt(t,r,i,a))}finally{o()}}async function ft(e,t){Y(t);let n=q.get(e);return n||(n={held:!1,waiters:[]},q.set(e,n)),n.held?new Promise((e,r)=>{let i,a=()=>{let e=n.waiters.indexOf(i);e<0||(n.waiters.splice(e,1),t.removeEventListener(`abort`,a),r(Z()))};i={signal:t,resolve:e,reject:r,abort:a},n.waiters.push(i),t.addEventListener(`abort`,a,{once:!0}),t.aborted&&a()}):(n.held=!0,pt(e,n))}function pt(e,t){let n=!1;return()=>{if(!n){for(n=!0;t.waiters.length>0;){let n=t.waiters.shift();if(n.signal.removeEventListener(`abort`,n.abort),n.signal.aborted){n.reject(Z());continue}n.resolve(pt(e,t));return}t.held=!1,q.get(e)===t&&q.delete(e)}}}async function J(e,t){Y(e);let n=await t();return Y(e),n}function Y(e){if(e.aborted)throw Z()}function mt(e,t,n,r){try{Y(n)}catch(e){return Promise.reject(e)}let i=vt(t);i.replaceChildren(yt(i,r),bt(i));let a=i.querySelector(`form`),o=i.querySelector(`h2`),s=i.querySelector(`.description`),c=a.elements.namedItem(`email`),l=a.elements.namedItem(`code`),u=i.querySelector(`.code`),d=i.querySelector(`button`),f=i.querySelector(`.error`),p=!1;return new Promise((t,r)=>{let m=!1,h=!1,g=!1,ee=()=>{n.removeEventListener(`abort`,v),i.removeEventListener(`keydown`,y),a.removeEventListener(`submit`,b)},_=e=>{m||(m=!0,ee(),e())},v=()=>{m||(g=!0,ee(),h||_(()=>r(Z())))},y=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),v()):t.key===`Tab`&&Tt(i,t)},b=async i=>{if(i.preventDefault(),!(m||h)){h=!0,f.textContent=``,d.disabled=!0,a.setAttribute(`aria-busy`,`true`);try{if(Y(n),!p){let t=c.value.trim();await J(n,async()=>{await e.auth.sendMagicCode({email:t})}),p=!0,c.readOnly=!0,u.hidden=!1,l.required=!0,o.textContent=`인증 코드`,s.textContent=`${t}로 보낸 코드를 입력하세요.`,d.textContent=`확인`,l.focus();return}await J(n,async()=>{await e.auth.signInWithMagicCode({email:c.value.trim(),code:l.value.trim()})});let r=await J(n,()=>e.getAuth());if(!r)throw Error(`인증 세션을 확인할 수 없습니다.`);_(()=>t(r))}catch(e){if(m||n.aborted||wt(e,`AUTH_CANCELLED`))return;f.textContent=_t(e)}finally{h=!1,!m&&(g||n.aborted)?_(()=>r(Z())):m||(d.disabled=!1,a.removeAttribute(`aria-busy`))}}};n.addEventListener(`abort`,v,{once:!0}),i.addEventListener(`keydown`,y),a.addEventListener(`submit`,b)})}function ht(e,t,n=``,r){if(t.aborted)return Promise.reject(Z());let i=vt(e);i.replaceChildren(yt(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(Z())),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 gt(e,t,n){if(t.aborted)return Promise.reject(Z());let r=vt(e);r.replaceChildren(yt(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(Z())),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)})}function _t(e){if(e&&typeof e==`object`&&`body`in e){let t=e.body;if(t?.message)return t.message}return e instanceof Error?e.message:`로그인에 실패했습니다. 다시 시도해 주세요.`}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=kt,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-login-title`),n.setAttribute(`aria-describedby`,`visual-review-login-description`);let r=X(t,`p`,`01.works`,`eyebrow`),i=X(t,`h2`,`Visual Review`);i.id=`visual-review-login-title`;let a=X(t,`p`,`초대받은 이메일로 계속하세요.`,`description`);a.id=`visual-review-login-description`;let o=t.createElement(`label`);o.append(`이메일`);let s=t.createElement(`input`);s.name=`email`,s.type=`email`,s.autocomplete=`email`,s.required=!0,o.append(s);let c=t.createElement(`label`);c.className=`code`,c.hidden=!0,c.append(`인증 코드`);let l=t.createElement(`input`);l.name=`code`,l.inputMode=`numeric`,l.autocomplete=`one-time-code`,c.append(l);let u=X(t,`p`,``,`error`);u.setAttribute(`role`,`alert`);let d=X(t,`button`,`코드 받기`);return d.type=`submit`,n.append(r,i,a,o,c,u,d),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=X(t,`p`,`01.works`,`eyebrow`),i=X(t,`h2`,`표시 이름`);i.id=`visual-review-name-title`;let a=X(t,`p`,`피드백에 이 이름이 표시됩니다.`,`description`);a.id=`visual-review-name-description`;let o=X(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=X(t,`p`,``,`error`);c.setAttribute(`role`,`alert`);let l=X(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-account-title`),n.setAttribute(`aria-describedby`,`visual-review-account-description`);let r=X(t,`p`,`01.works`,`eyebrow`),i=X(t,`h2`,`계정 확인`);i.id=`visual-review-account-title`;let a=X(t,`p`,`이 초대는 현재 로그인한 계정과 일치하지 않습니다.`,`description`);a.id=`visual-review-account-description`;let o=X(t,`button`,`다른 계정으로 계속`);return o.type=`submit`,n.append(r,i,a,o),n}function X(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 Z(){return new ot(`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=`
|
|
1
|
+
import{r as e}from"./install-C-4G_vDp.js";import{t}from"./generated-frame-CkUKpj5U.js";import{i as n,init as r}from"@instantdb/core";const i=n.schema({entities:{$users:n.entity({email:n.string().unique().indexed()}),projects:n.entity({name:n.string(),slug:n.string().unique().indexed(),allowedOrigin: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()}),sourceMapUploadTokens:n.entity({projectId:n.string().indexed(),tokenHash:n.string().unique().indexed(),tokenPrefix:n.string(),scope:n.string(),expiresAt:n.number().indexed(),revokedAt:n.number().optional(),createdAt:n.number().indexed()}),sourceMapReleases:n.entity({projectId:n.string().indexed(),buildId:n.string().indexed(),gitCommit:n.string().optional(),mode:n.string(),framework:n.string(),frameworkVersion:n.string().optional(),status:n.string().indexed(),expiresAt:n.number().indexed(),createdAt:n.number().indexed(),updatedAt:n.number(),completedAt:n.number().optional()}),sourceMapArtifacts:n.entity({releaseId:n.string().indexed(),generatedPath:n.string().indexed(),runtime:n.string().indexed(),objectKey:n.string().unique().indexed(),mapSha256:n.string().indexed(),generatedSha256:n.string(),debugId:n.string().optional(),byteSize:n.number(),createdAt: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()}),comments:n.entity({pageId:n.string().indexed(),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(),status:n.string().indexed(),workflowRevision:n.number(),createdAt:n.number().indexed(),updatedAt:n.number().indexed(),resolvedAt:n.number().optional(),resolvedById:n.string().optional()}),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`}},pageCurrentBuild:{forward:{on:`reviewPageBuilds`,has:`one`,label:`page`,required:!0,onDelete:`cascade`},reverse:{on:`reviewPages`,has:`one`,label:`currentBuild`}},projectSourceMapUploadTokens:{forward:{on:`projects`,has:`many`,label:`uploadTokens`},reverse:{on:`sourceMapUploadTokens`,has:`one`,label:`project`,required:!0,onDelete:`cascade`}},projectSourceMapReleases:{forward:{on:`projects`,has:`many`,label:`sourceMapReleases`},reverse:{on:`sourceMapReleases`,has:`one`,label:`project`,required:!0,onDelete:`cascade`}},sourceMapReleaseArtifacts:{forward:{on:`sourceMapReleases`,has:`many`,label:`artifacts`},reverse:{on:`sourceMapArtifacts`,has:`one`,label:`release`,required:!0,onDelete:`cascade`}},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:`one`,label:`activeReviewInvitation`}},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`}},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(),cursorX:n.number().optional(),cursorY:n.number().optional(),viewportWidth:n.number().optional(),viewportHeight:n.number().optional()})}}}),a=new Uint8Array([107,167,184,17,157,173,17,209,128,180,0,192,79,212,48,200]);function o(e,t,n){return u(e,n),`${e}:${t}:${n}`}async function s(e,t,n){return l(o(e,t,n))}async function c(e){if(!e.trim())throw Error(`Comment ID is required for source context`);return l(`${e}:source-context`)}async function l(e){let t=globalThis.crypto?.subtle;if(!t)throw Error(`Web Crypto is required to persist review capture context`);let n=new TextEncoder().encode(`01works.visual-review/v1/${e}`),r=new Uint8Array(a.length+n.length);r.set(a),r.set(n,a.length);let i=new Uint8Array(await t.digest(`SHA-1`,r)).slice(0,16);i[6]=i[6]&15|80,i[8]=i[8]&63|128;let o=[...i].map(e=>e.toString(16).padStart(2,`0`)).join(``);return`${o.slice(0,8)}-${o.slice(8,12)}-${o.slice(12,16)}-${o.slice(16,20)}-${o.slice(20)}`}function u(e,t){if(!e.trim())throw Error(`Comment ID is required for capture context`);if(!Number.isSafeInteger(t)||t<0)throw Error(`Capture child ordinal must be a non-negative integer`)}const d=131072,f=32768,p=4096,m=1e3;var h=class extends Error{constructor(e,t){super(e,t),this.name=`InstantCaptureIntegrityError`}};function g(e){let t=re(e,`comment target`,!0),n={kind:t.kind,anchor:ue(t.anchor),region:pe(t.region),elements:t.elements.map(e=>({selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,rect:pe(e.rect),source:null,componentStack:[]})),pageUrl:t.pageUrl,pageTitle:t.pageTitle,capturedAt:t.capturedAt},r={elements:t.elements.map(e=>({selector:e.selector,source:e.source?me(e.source):null,componentStack:e.componentStack.map(me)})),...t.sourceProvenance?{sourceProvenance:he(t.sourceProvenance)}:{}};M(n,d,`Public target`);let i=xe(r,65536,`Source context`);return{publicTarget:n,commentFields:y(n),targetElements:n.elements.map(b),sourceContextJson:i}}function ee(e,t,n){let r=T(e,n),i={selector:E(r.anchorSelector,`${n} anchor selector`,p),offsetX:A(r.anchorOffsetX,`${n} anchor offsetX`),offsetY:A(r.anchorOffsetY,`${n} anchor offsetY`),viewportX:A(r.anchorViewportX,`${n} anchor viewportX`),viewportY:A(r.anchorViewportY,`${n} anchor viewportY`)},a=x({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:fe({origin:D(r.targetPageOrigin,`${n} page origin`,1024),pathname:D(r.targetPagePathname,`${n} page pathname`,4096),search:E(r.targetPageSearch,`${n} page search`,1024),hash:E(r.targetPageHash,`${n} page hash`,1024)}),pageTitle:r.targetPageTitle,capturedAt:r.targetCapturedAt},n),o=te(t,`${n} elements`),s=a;for(let e of o)try{s=x({...a,elements:[...s.elements,e]},n)}catch{}return s}function _(e){let t=ne(e);return t?Object.entries(t).map(([e,t],n)=>typeof t==`string`?{ordinal:n,key:e,valueType:`string`,stringValue:t}:typeof t==`number`?{ordinal:n,key:e,valueType:`number`,numberValue:t}:typeof t==`boolean`?{ordinal:n,key:e,valueType:`boolean`,booleanValue:t}:{ordinal:n,key:e,valueType:`null`}):[]}function v(e){if(!Array.isArray(e)||e.length===0)return;let t=[...e].map(e=>{try{let t=T(e,`Comment scope entry`);return{row:t,ordinal:k(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=D(e.key,`Comment scope key`,256);if(Object.hasOwn(n,t))continue;switch(e.valueType){case`string`:n[t]=E(e.stringValue,`Comment scope ${t}`,m);break;case`number`:n[t]=O(e.numberValue,`Comment scope ${t}`);break;case`boolean`:if(typeof e.booleanValue!=`boolean`)throw N(`Comment scope ${t} is invalid`);n[t]=e.booleanValue;break;case`null`:n[t]=null;break;default:throw N(`Comment scope ${t} is invalid`)}}catch{}}if(Object.keys(n).length!==0)try{return M(n,f,`Comment scope`),n}catch{return}}function y(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:de(t.pathname),targetPageSearch:t.search.slice(1),targetPageHash:t.hash.slice(1),targetPageTitle:e.pageTitle,targetCapturedAt:e.capturedAt}}function b(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 te(e,t){if(!Array.isArray(e)||e.length===0)return[];let n=[...e].map(e=>{try{let n=T(e,t);return{row:n,ordinal:k(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(ie({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 x(e,t){return re(e,t,!1)}function S(e,t=`Comment body`){return D(e,t,2e4)}function C(e,t=`Comment body`){let n=S(e,t);for(let e of n)if(e.trim())return e;throw N(`${t} is empty`)}function ne(e){if(e==null)return;let t=T(e,`Comment scope`);if(Object.keys(t).length>20)throw N(`Comment scope has too many fields`);let n={};for(let[e,r]of Object.entries(t)){if(!e.trim()||e.length>256)throw N(`Comment scope has an invalid key`);if(typeof r==`string`){if(r.length>m)throw N(`Comment scope ${e} is too long`);n[e]=r}else if(typeof r==`number`)n[e]=O(r,`Comment scope ${e}`);else if(typeof r==`boolean`||r===null)n[e]=r;else throw N(`Comment scope ${e} is invalid`)}return M(n,f,`Comment scope`),n}function re(e,t,n){let r=w(e,t,[`kind`,`anchor`,`region`,`elements`,`pageUrl`,`pageTitle`,`capturedAt`,`sourceProvenance`],[`sourceProvenance`]),i=r.kind;if(i!==`element`&&i!==`region`&&i!==`viewport`)throw N(`${t} kind is invalid`);let a=ge(r.elements,`${t} elements`);if(a.length>8)throw N(`${t} contains too many elements`);if(!n&&r.sourceProvenance!=null)throw N(`${t} exposes source provenance`);let o=D(r.pageUrl,`${t} pageUrl`,8192);be(o,`${t} pageUrl`);let s={kind:i,anchor:ae(r.anchor,`${t} anchor`),region:oe(r.region,`${t} region`),elements:a.map((e,r)=>ie(e,`${t} elements[${r}]`,n)),pageUrl:o,pageTitle:E(r.pageTitle,`${t} pageTitle`,m),capturedAt:j(r.capturedAt,`${t} capturedAt`),...n&&r.sourceProvenance!=null?{sourceProvenance:le(r.sourceProvenance,`${t} provenance`)}:{}};return M(s,n?196608:d,t),s}function ie(e,t,n){let r=w(e,t,[`selector`,`tagName`,`textPreview`,`rect`,`source`,`componentStack`]),i=ge(r.componentStack,`${t} componentStack`);if(i.length>32)throw N(`${t} componentStack is too large`);if(!n&&(r.source!=null||i.length>0))throw N(`${t} exposes source metadata`);return{selector:D(r.selector,`${t} selector`,p),tagName:D(r.tagName,`${t} tagName`,128),textPreview:E(r.textPreview,`${t} textPreview`,m),rect:oe(r.rect,`${t} rect`),source:n&&r.source!=null?se(r.source,`${t} source`):null,componentStack:n?i.map((e,n)=>se(e,`${t} stack[${n}]`)):[]}}function ae(e,t){let n=w(e,t,[`selector`,`offsetX`,`offsetY`,`viewportX`,`viewportY`]);return{selector:E(n.selector,`${t} selector`,p),offsetX:A(n.offsetX,`${t} offsetX`),offsetY:A(n.offsetY,`${t} offsetY`),viewportX:A(n.viewportX,`${t} viewportX`),viewportY:A(n.viewportY,`${t} viewportY`)}}function oe(e,t){let n=w(e,t,[`pageX`,`pageY`,`width`,`height`,`viewportX`,`viewportY`,`viewportWidth`,`viewportHeight`]),r={pageX:O(n.pageX,`${t} pageX`),pageY:O(n.pageY,`${t} pageY`),width:O(n.width,`${t} width`),height:O(n.height,`${t} height`),viewportX:O(n.viewportX,`${t} viewportX`),viewportY:O(n.viewportY,`${t} viewportY`),viewportWidth:O(n.viewportWidth,`${t} viewportWidth`),viewportHeight:O(n.viewportHeight,`${t} viewportHeight`)};if(r.width<0||r.height<0||r.viewportWidth<0||r.viewportHeight<0)throw N(`${t} has a negative dimension`);return r}function se(e,t){let n=w(e,t,[`filePath`,`lineNumber`,`columnNumber`,`componentName`,`origin`,`generated`],[`generated`]),r=n.origin;if(r!==`app`&&r!==`shared-ui`&&r!==`dependency`&&r!==`generated`&&r!==`unknown`)throw N(`${t} origin is invalid`);return{filePath:D(n.filePath,`${t} filePath`,p),lineNumber:ye(n.lineNumber,`${t} lineNumber`),columnNumber:ye(n.columnNumber,`${t} columnNumber`),componentName:n.componentName==null?null:D(n.componentName,`${t} componentName`,512),origin:r,...n.generated===void 0?{}:{generated:ce(n.generated,`${t} generated`)}}}function ce(e,n){let r=w(e,n,[`assetPath`,`line1`,`column0`,`runtime`,`debugId`],[`debugId`]),i=t(r.assetPath);if(!i)throw N(`${n} assetPath is invalid`);let a=r.runtime;if(a!==`browser`&&a!==`server-node`&&a!==`server-edge`&&a!==`unknown`)throw N(`${n} runtime is invalid`);return{assetPath:i,line1:k(r.line1,`${n} line1`,1,1e7),column0:k(r.column0,`${n} column0`,0,1e7),runtime:a,...r.debugId===void 0?{}:{debugId:ve(r.debugId,`${n} debugId`)}}}function le(e,t){let n=w(e,t,[`provider`,`build`,`resolvedAt`,`sourceMapStatus`]),r=n.provider;if(r!==`react-grab`&&r!==`embedded`&&r!==`custom`)throw N(`${t} provider is invalid`);let i=n.sourceMapStatus;if(i!==`resolved`&&i!==`fallback`&&i!==`unavailable`)throw N(`${t} sourceMapStatus is invalid`);let a=w(n.build,`${t} build`,[`buildId`,`gitCommit`,`generatedAt`,`mode`],[`generatedAt`]),o=a.mode;if(o!==`development`&&o!==`preview`&&o!==`production`)throw N(`${t} build mode is invalid`);return{provider:r,build:{buildId:D(a.buildId,`${t} buildId`,512),gitCommit:a.gitCommit==null?null:D(a.gitCommit,`${t} gitCommit`,256),...a.generatedAt==null?{}:{generatedAt:j(a.generatedAt,`${t} generatedAt`)},mode:o},resolvedAt:j(n.resolvedAt,`${t} resolvedAt`),sourceMapStatus:i}}function ue(e){return{...e}}function de(e){return e.replace(/\/+$/,``)||`/`}function fe(e){return`${e.origin}${e.pathname}${e.search?`?${e.search}`:``}${e.hash?`#${e.hash}`:``}`}function pe(e){return{...e}}function me(e){return{...e,...e.generated?{generated:{...e.generated}}:{}}}function he(e){return{...e,build:{...e.build}}}function w(e,t,n,r=[]){let i=T(e,t);if(Object.keys(i).some(e=>!n.includes(e)))throw N(`${t} contains unknown fields`);for(let e of n)if(!r.includes(e)&&!Object.hasOwn(i,e))throw N(`${t} is missing ${e}`);return i}function T(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw N(`${t} is missing or invalid`);return e}function ge(e,t){if(!Array.isArray(e))throw N(`${t} is missing or invalid`);return e}function E(e,t,n){if(typeof e!=`string`||_e(e,n)>n)throw N(`${t} is invalid or too long`);return e}function _e(e,t){let n=0;for(let r of e)if(n+=1,n>t)return n;return n}function D(e,t,n){let r=E(e,t,n);if(!r.trim())throw N(`${t} is empty`);return r}function O(e,t){if(typeof e!=`number`||!Number.isFinite(e))throw N(`${t} is invalid`);return e}function k(e,t,n,r){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<n||e>r)throw N(`${t} is invalid`);return e}function ve(e,t){let n=D(e,t,256);if(!/^[A-Za-z0-9._:-]+$/u.test(n))throw N(`${t} is invalid`);return n}function A(e,t){let n=O(e,t);if(n<0||n>1)throw N(`${t} is outside 0..1`);return n}function j(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw N(`${t} is invalid`);return e}function ye(e,t){if(e===null)return null;if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0)throw N(`${t} is invalid`);return e}function be(e,t){let n;try{n=new URL(e)}catch(e){throw N(`${t} is invalid`,e)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw N(`${t} must use HTTP or HTTPS`)}function M(e,t,n){xe(e,t,n)}function xe(e,t,n){let r;try{r=JSON.stringify(e)}catch(e){throw N(`${n} cannot be serialized`,e)}if(r.length>t)throw N(`${n} is too large`);return r}function N(e,t){return new h(e,{cause:t instanceof Error?t:void 0})}function Se(e){if(!e.trim())throw Error(`InstantDB app ID is required`);return r({appId:e,schema:i})}var Ce=class{db;session;#e;constructor(e,t,n={}){this.db=e,this.session=t,this.#e=n.commentTransport}async getSnapshot(e){let{data:t}=await this.db.queryOnce(we(e,this.session.authUserId));return Te(e,t.comments,t.replies)}subscribe(e,t,n){return this.db.subscribeQuery(we(e,this.session.authUserId),r=>{if(r.error){n?.(Me(r.error));return}if(r.data)try{t(Te(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=S(n.body).trim(),i=C(r),a=L(n.createdAt,`Comment createdAt`),l=L(n.updatedAt,`Comment updatedAt`);if(l<a)throw new h(`Comment updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new h(`Comment edits must go through the review service`);if(n.status!==`open`||n.resolvedAt!==void 0||n.resolvedById!==void 0)throw new h(`New comments must start open`);let u=g(n.target);if(!ke(n.anchor,u.publicTarget.anchor))throw new h(`Comment anchor does not match its target`);if(this.#e){await this.#e.createComment({pageId:e,commentId:n.id,body:r,target:n.target,...n.scope===void 0?{}:{scope:n.scope}});return}let d=_(n.scope),f=await Promise.all(u.targetElements.map(async e=>({element:e,id:await s(n.id,`element`,e.ordinal),slotKey:o(n.id,`element`,e.ordinal)}))),p=await Promise.all(d.map(async e=>({entry:e,id:await s(n.id,`scope`,e.ordinal),slotKey:o(n.id,`scope`,e.ordinal)}))),m=await c(n.id);await this.db.transact([this.db.tx.comments[n.id].update({pageId:e,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:r,bodyContentMarker:i,...u.commentFields,status:n.status,workflowRevision:0,createdAt:a,updatedAt:l}).link({page:e,author:this.session.reviewerId}),...f.map(({element:e,id:t,slotKey:r})=>this.db.tx.commentTargetElements[t].update({commentId:n.id,slotKey:r,authorAuthUserId:this.session.authUserId,...e}).link({comment:n.id})),...p.map(({entry:e,id:t,slotKey:r})=>this.db.tx.commentScopeEntries[t].update({commentId:n.id,slotKey:r,authorAuthUserId:this.session.authUserId,...e}).link({comment:n.id})),this.db.tx.commentSourceContexts[m].update({commentId:n.id,pageId:e,authorAuthUserId:this.session.authUserId,contextJson:u.sourceContextJson,createdAt:a}).link({comment:n.id,page:e,author:this.session.reviewerId})]);return}case`comment.delete`:throw new h(`Comment deletion must go through the review service`);case`reply.upsert`:{let n=t.reply;if(n.authorId!==this.session.reviewerId)throw Error(`Reply author mismatch`);let r=S(n.body,`Reply body`).trim(),i=C(r,`Reply body`),a=L(n.createdAt,`Reply createdAt`),o=L(n.updatedAt,`Reply updatedAt`);if(o<a)throw new h(`Reply updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new h(`Reply edits must go through the review service`);if(this.#e){await this.#e.createReply({commentId:n.commentId,replyId:n.id,body:r});return}await this.db.transact(this.db.tx.replies[n.id].update({pageId:e,commentId:n.commentId,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:r,bodyContentMarker:i,createdAt:a,updatedAt:o}).link({comment:n.commentId,author:this.session.reviewerId}));return}case`reply.delete`:throw new h(`Reply deletion must go through the review service`)}}};function we(e,t){return{comments:{$:{where:{pageId:e},order:{createdAt:`asc`}},targetElements:{},scopeEntries:{}},replies:{$:{where:{pageId:e},order:{createdAt:`asc`}}},$users:{$:{where:{id:t}},activeReviewInvitation:{project:{}}}}}function Te(e,t,n){let r=t.map(t=>Ee(t,e));je(r,`comment`);let i=new Set(r.map(({id:e})=>e)),a=n.map(t=>De(t,e));je(a,`reply`);for(let e of a)if(!i.has(e.commentId))throw new h(`Reply ${e.id} references a comment outside the page snapshot`);return{pageId:e,comments:r,replies:a}}function Ee(e,t){let n=P(e,`comment`),r=F(n.id,`comment id`);if(F(n.pageId,`comment ${r} pageId`)!==t)throw new h(`Comment ${r} escaped its page scope`);F(n.authorAuthUserId,`comment ${r} authorAuthUserId`);let i=!(Object.hasOwn(n,`anchor`)&&Object.hasOwn(n,`target`)),a=i?ee(n,n.targetElements,`comment ${r} target`):x(n.target,`comment ${r} target`),o=i?{...a.anchor}:Oe(n.anchor,`comment ${r} anchor`);if(!ke(o,a.anchor))throw new h(`Comment ${r} has inconsistent anchors`);let s=n.status;if(s!==`open`&&s!==`resolved`)throw new h(`Comment ${r} has an invalid status`);let c=L(n.createdAt,`comment ${r} createdAt`),l=L(n.updatedAt,`comment ${r} updatedAt`);if(l<c)throw new h(`Comment ${r} updatedAt precedes createdAt`);let u=Ie(n.resolvedAt,`comment ${r} resolvedAt`),d=Le(n.resolvedById,`comment ${r} resolvedById`);if(s===`open`&&(u!==void 0||d!==void 0))throw new h(`Open comment ${r} contains resolution metadata`);if(s===`resolved`&&(u===void 0||d===void 0||u!==l))throw new h(`Resolved comment ${r} has invalid workflow metadata`);return{id:r,pageId:t,authorId:F(n.authorId,`comment ${r} authorId`),authorName:F(n.authorName,`comment ${r} authorName`),body:S(n.body,`comment ${r} body`),anchor:o,target:a,...i?Ae(v(n.scopeEntries)):n.scope==null?{}:{scope:ne(n.scope)},status:s,workflowRevision:Fe(n.workflowRevision,`comment ${r} workflowRevision`),createdAt:c,updatedAt:l,...u===void 0?{}:{resolvedAt:u},...d===void 0?{}:{resolvedById:d}}}function De(e,t){let n=P(e,`reply`),r=F(n.id,`reply id`);if(F(n.pageId,`reply ${r} pageId`)!==t)throw new h(`Reply ${r} escaped its page scope`);F(n.authorAuthUserId,`reply ${r} authorAuthUserId`);let i=L(n.createdAt,`reply ${r} createdAt`),a=L(n.updatedAt,`reply ${r} updatedAt`);if(a<i)throw new h(`Reply ${r} updatedAt precedes createdAt`);return{id:r,commentId:F(n.commentId,`reply ${r} commentId`),authorId:F(n.authorId,`reply ${r} authorId`),authorName:F(n.authorName,`reply ${r} authorName`),body:S(n.body,`reply ${r} body`),createdAt:i,updatedAt:a}}function Oe(e,t){let n=P(e,t);if(Object.keys(n).length!==5||!Object.hasOwn(n,`selector`)||!Object.hasOwn(n,`offsetX`)||!Object.hasOwn(n,`offsetY`)||!Object.hasOwn(n,`viewportX`)||!Object.hasOwn(n,`viewportY`))throw new h(`${t} has invalid fields`);return{selector:Pe(n.selector,`${t} selector`),offsetX:I(n.offsetX,`${t} offsetX`),offsetY:I(n.offsetY,`${t} offsetY`),viewportX:I(n.viewportX,`${t} viewportX`),viewportY:I(n.viewportY,`${t} viewportY`)}}function ke(e,t){return e.selector===t.selector&&e.offsetX===t.offsetX&&e.offsetY===t.offsetY&&e.viewportX===t.viewportX&&e.viewportY===t.viewportY}function Ae(e){return e===void 0?{}:{scope:e}}function je(e,t){let n=new Set;for(let r of e){if(n.has(r.id))throw new h(`Duplicate ${t} ${r.id}`);n.add(r.id)}}function Me(e){let t=Ne(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 Ne(e){return e instanceof Error?e.message:e&&typeof e==`object`&&`message`in e?String(e.message):``}function P(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new h(`${t} is missing or invalid`);return e}function Pe(e,t){if(typeof e!=`string`)throw new h(`${t} is invalid`);return e}function F(e,t){let n=Pe(e,t);if(!n.trim())throw new h(`${t} is empty`);return n}function I(e,t){if(typeof e!=`number`||!Number.isFinite(e)||e<0||e>1)throw new h(`${t} is invalid`);return e}function L(e,t){if(!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw new h(`${t} is invalid`);return e}function Fe(e,t){if(!Number.isSafeInteger(e)||e<0)throw new h(`${t} is invalid`);return e}function Ie(e,t){return e==null?void 0:L(e,t)}function Le(e,t){return e==null?void 0:F(e,t)}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`}),Object.freeze({comments:200,replies:1e3,sourceContexts:200});var Re=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=qe(e,t.roomId),a,l,u=this.roomCredential??{id:t.roomId,expiresAt:2**53-1,refresh:async()=>void 0},d=t=>{let o=this.db.joinRoom(`visualReview`,t),s=o.subscribePresence({},e=>{if(e.error){r?.(Ye(e.error));return}i=Object.values(e.peers).map(e=>Be(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?.()},f=()=>{if(!this.roomCredential||o)return;let e=Math.max(1e3,u.expiresAt-Date.now()+250);l=setTimeout(()=>{p()},e)},p=async()=>{try{let e=await u.refresh();if(o||!e)return;u={...e,refresh:u.refresh},d(e.id),f()}catch(e){if(o)return;r?.(Ye(e)),o||(l=setTimeout(()=>{p()},5e3))}};d(u.id),f(),s.push(()=>{l&&clearTimeout(l),this.#e.delete(n),a?.()})}return t.chat&&s.push(this.db.subscribeQuery(ze(e,this.session.authUserId),t=>{if(t.error){r?.(Ye(t.error));return}if(t.data)try{a=t.data.reviewMessages.map(t=>Ve(t,e)).sort(Je),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(qe(e,t));r&&r.publishPresence({reviewerId:this.session.reviewerId,displayName:this.session.displayName,color:n.color,active:n.active,...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}})}async sendMessage(e,t){if(t.pageId!==e)throw Error(`Review message page mismatch`);if(t.authorId!==this.session.reviewerId)throw Error(`Review message author mismatch`);let n=He(t.body),r=Ue(t.pathname),i=z(t.createdAt,`Review message createdAt`),a=z(t.updatedAt,`Review message updatedAt`);if(i!==a)throw Error(`New review messages must be immutable`);await this.db.transact(this.db.tx.reviewMessages[t.id].update({pageId:e,pathname:r,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:n,bodyContentMarker:C(n,`Review message body`),createdAt:i,updatedAt:a}).link({page:e,author:this.session.reviewerId}))}};function ze(e,t){return{reviewMessages:{$:{where:{pageId:e},order:{createdAt:`asc`}}},$users:{$:{where:{id:t}},activeReviewInvitation:{project:{}}}}}function Be(e){let t=We(e.reviewerId,128),n=We(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=Ge(e.cursorX),a=Ge(e.cursorY),o=Ke(e.viewportWidth),s=Ke(e.viewportHeight);return{peerId:e.peerId,reviewerId:t,displayName:n,color:r,active:e.active,...i===void 0?{}:{cursorX:i},...a===void 0?{}:{cursorY:a},...o===void 0?{}:{viewportWidth:o},...s===void 0?{}:{viewportHeight:s}}}function Ve(e,t){let n=R(e.id,`Review message id`,128);if(R(e.pageId,`Review message pageId`,128)!==t)throw Error(`Review message page mismatch`);return{id:n,pageId:t,pathname:Ue(e.pathname),authorId:R(e.authorId,`Review message authorId`,128),authorName:R(e.authorName,`Review message authorName`,512),body:He(e.body),createdAt:z(e.createdAt,`Review message createdAt`),updatedAt:z(e.updatedAt,`Review message updatedAt`)}}function He(e){return R(e,`Review message body`,4e3)}function Ue(e){let t=R(e,`Review message pathname`,2e3);if(!t.startsWith(`/`))throw Error(`Review message pathname is invalid`);return t}function R(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 We(e,t){if(typeof e!=`string`)return null;let n=e.trim();return n&&n.length<=t?n:null}function Ge(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function Ke(e){let t=Ge(e);return t!==void 0&&t>0?t:void 0}function z(e,t){if(!Number.isSafeInteger(e)||e<0)throw Error(`${t} is invalid`);return e}function qe(e,t){return JSON.stringify([e,t])}function Je(e,t){return e.createdAt-t.createdAt||e.id.localeCompare(t.id)}function Ye(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`});const B={$default:`false`},V={$default:`false`},H=`$user.activeReviewInvitation.project.id`;function U(e){return[`auth.id != null`,`size(auth.ref('$user.activeReviewInvitation.id')) == 1`,`size(auth.ref('${H}')) == 1`,`size(auth.ref('$user.activeReviewInvitation.status')) == 1`,`size(auth.ref('$user.activeReviewInvitation.expiresAt')) == 1`,`size(auth.ref('$user.activeReviewInvitation.revokedAt')) == 0`,`auth.ref('$user.activeReviewInvitation.status')[0] == 'accepted'`,`request.time < timestamp(auth.ref('$user.activeReviewInvitation.expiresAt')[0])`,e].join(` && `)}function W(...e){return e.map(e=>`(${e})`).join(` && `)}function G(...e){return e.map(e=>`(${e})`).join(` || `)}function K(e,t){return`!has(${e}.${t}) || ${e}.${t} == null`}const Xe=`actions.data == 'create' && actions.linkedData == 'update'`,Ze=e=>`${e}.matches('[^ \\t\\n\\r\\f\\u000b\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]')`,Qe=e=>W(`${e} >= 0`,`${e} <= 253402300799999`,`${e} % 1 == 0`),$e=e=>W(Qe(e),`(request.time - timestamp(${e})).getSeconds() <= 86400`,`(request.time - timestamp(${e})).getSeconds() >= -300`);W(`actions.data == 'update' && actions.linkedData == 'create'`,G(`auth.id != null && auth.id in data.ref('project.owners.id')`,U(`auth.ref('${H}')[0] in data.ref('project.id')`))),W(Xe,G(`auth.id != null && auth.id in data.ref('page.project.owners.id')`,U(`auth.ref('${H}')[0] in data.ref('page.project.id')`)),`auth.id != null && auth.id == data.authorAuthUserId && auth.id in data.ref('author.$user.id')`,`data.pageId in data.ref('page.id')`,`data.authorId in data.ref('author.id') && data.authorAuthUserId in data.ref('author.$user.id') && data.authorName in data.ref('author.displayName')`,`data.pageId in data.ref('author.project.pages.id')`),W(Xe,`data.pageId == linkedData.id`,`auth.id != null && auth.id == data.authorAuthUserId`,`data.authorId in auth.ref('$user.reviewerMemberships.id')`,`data.authorId in linkedData.ref('project.reviewers.id')`,G(`auth.id != null && auth.id in linkedData.ref('project.owners.id')`,U(`auth.ref('${H}')[0] in linkedData.ref('project.id')`)));const et=`auth.id != null && auth.id in data.ref('comment.page.project.owners.id')`,tt=U(`auth.ref('${H}')[0] in data.ref('comment.page.project.id')`);U(`auth.ref('${H}')[0] in data.ref('comment.page.project.id')`),U(`auth.ref('${H}')[0] in data.ref('page.project.id')`);const nt=W(`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')`);W(`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`,nt),W(`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`,nt),W(`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')`),W(`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')`),W(`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')`),{...B},{...V},{...V},U(`data.id == auth.ref('${H}')[0]`),{...B},W(`isOwner`,G(W(K(`data`,`allowedOrigin`),K(`newData`,`allowedOrigin`)),`newData.allowedOrigin == data.allowedOrigin`)),{...V},{...B},W(`isOwner`,G(W(K(`data`,`autoRegistrationSlot`),K(`newData`,`autoRegistrationSlot`)),`newData.autoRegistrationSlot == data.autoRegistrationSlot`)),{...V},{...B},{...V},{...B},{...V},{...B},{...V},{...B},{...V},U(`auth.ref('${H}')[0] in data.ref('project.id')`),{...B},{...V},{...B},{...B},{...V},{...V},{...B},{...V},{...B},G(et,tt),{...B},G(et,tt),{...B},{...B},W(`data.createdAt == data.updatedAt`,$e(`data.createdAt`),`size(data.body) > 0`,`size(data.body) <= 4000`,`size(data.bodyContentMarker) == 1`,Ze(`data.bodyContentMarker`),`data.body.startsWith(data.bodyContentMarker)`,`size(data.authorName) > 0`,`size(data.authorName) <= 512`,Ze(`data.authorName`),`size(data.pathname) > 0`,`size(data.pathname) <= 2000`,`request.modifiedFields.all(field, field in ['pageId', 'pathname', 'authorId', 'authorAuthUserId', 'authorName', 'body', 'bodyContentMarker', 'createdAt', 'updatedAt', 'page', 'author'])`),{...B},{...V};var rt=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewerCommentSaveError`}};function it(e,t){let n=e.replace(/\/+$/,``),r=async(e,r)=>{let i=await t();if(!i)throw new rt(`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 rt(`NETWORK`,`리뷰 서버에 연결하지 못했습니다. 연결을 확인하고 다시 시도해 주세요.`)}if(!a.ok)throw new rt(...await at(a))};return{createComment:e=>r(`/v1/comments`,e),createReply:e=>r(`/v1/replies`,e)}}async function at(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 ot=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewBootstrapError`}};const q=new Map;function st(e,t={}){let n=e.trim();if(!n)throw Error(`InstantDB app ID is required`);return{async resolve(e){let r=(t.databaseFactory??Se)(n),i=await ut(n,r,e.authHost,e.signal,e.styleNonce,t.reviewerToken);for(;;)try{await ct(t.acceptInvitation,{refreshToken:i.refresh_token,invitationId:e.invitationId,suggestedDisplayName:Ct(i.email),authHost:e.authHost,signal:e.signal,styleNonce:e.styleNonce});break}catch(a){if(!wt(a,`INVITATION_EMAIL_MISMATCH`))throw a;await gt(e.authHost,e.signal,e.styleNonce),i=await dt(n,r,i,e.authHost,e.signal,e.styleNonce,t.reviewerToken)}let{data:a}=await r.queryOnce({reviewers:{$:{where:{authUserId:i.id}}},reviewPages:{$:{where:{stagingOrigin:e.location.origin}}},invitations:{}}),o=lt(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 ot(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=e.collaboration?.cursors===!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,l=c&&t.resolveCollaborationRoom?{...c,refresh:async()=>{let n=await r.getAuth();if(n?.refresh_token)return t.resolveCollaborationRoom?.({refreshToken:n.refresh_token,invitationId:e.invitationId,pageId:o.page.id,scopeId:e.collaboration.scopeId,signal:e.signal})}}:void 0;return{pageId:o.page.id,session:s,repository:new Ce(r,s,{...t.serviceUrl===void 0?{}:{commentTransport:it(t.serviceUrl,async()=>(await r.getAuth())?.refresh_token??null)}}),...e.collaboration?.cursors===!0||e.collaboration?.chat===!0?{collaborationRepository:new Re(r,s,l)}:{},...e.collaboration?.cursors===!0&&l?{collaborationRoomId:l.id}:{},allowedStagingHosts:[e.location.hostname]}}}}async function ct(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 ht(t.authHost,t.signal,t.suggestedDisplayName,t.styleNonce);await e({...n,displayName:r})}function lt(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=n.find(e=>e.projectId===i.projectId&&e.stagingOrigin===r.location.origin&&Et(e.pathname)===o);return s?{ok:!0,invitation:i,reviewer:a,page:s}:{ok:!1,code:`PAGE_NOT_FOUND`}}async function ut(e,t,n,r,i,a){let o=await J(r,()=>t.getAuth());if(o)return o;let s=await ft(e,r);try{return await J(r,()=>t.getAuth())||(a?await J(r,async()=>{await t.auth.signInWithToken(a);let e=await t.getAuth();if(!e)throw Error(`Reviewer session did not establish`);return e}):await mt(t,n,r,i))}finally{s()}}async function dt(e,t,n,r,i,a,o){Y(i);let s=await ft(e,i);try{let e=await J(i,()=>t.getAuth());return e&&e.id!==n.id?e:(e&&await J(i,async()=>{await t.auth.signOut()}),Y(i),o?await J(i,async()=>{await t.auth.signInWithToken(o);let e=await t.getAuth();if(!e)throw Error(`Reviewer session did not establish`);return e}):await mt(t,r,i,a))}finally{s()}}async function ft(e,t){Y(t);let n=q.get(e);return n||(n={held:!1,waiters:[]},q.set(e,n)),n.held?new Promise((e,r)=>{let i,a=()=>{let e=n.waiters.indexOf(i);e<0||(n.waiters.splice(e,1),t.removeEventListener(`abort`,a),r(Z()))};i={signal:t,resolve:e,reject:r,abort:a},n.waiters.push(i),t.addEventListener(`abort`,a,{once:!0}),t.aborted&&a()}):(n.held=!0,pt(e,n))}function pt(e,t){let n=!1;return()=>{if(!n){for(n=!0;t.waiters.length>0;){let n=t.waiters.shift();if(n.signal.removeEventListener(`abort`,n.abort),n.signal.aborted){n.reject(Z());continue}n.resolve(pt(e,t));return}t.held=!1,q.get(e)===t&&q.delete(e)}}}async function J(e,t){Y(e);let n=await t();return Y(e),n}function Y(e){if(e.aborted)throw Z()}function mt(e,t,n,r){try{Y(n)}catch(e){return Promise.reject(e)}let i=vt(t);i.replaceChildren(yt(i,r),bt(i));let a=i.querySelector(`form`),o=i.querySelector(`h2`),s=i.querySelector(`.description`),c=a.elements.namedItem(`email`),l=a.elements.namedItem(`code`),u=i.querySelector(`.code`),d=i.querySelector(`button`),f=i.querySelector(`.error`),p=!1;return new Promise((t,r)=>{let m=!1,h=!1,g=!1,ee=()=>{n.removeEventListener(`abort`,v),i.removeEventListener(`keydown`,y),a.removeEventListener(`submit`,b)},_=e=>{m||(m=!0,ee(),e())},v=()=>{m||(g=!0,ee(),h||_(()=>r(Z())))},y=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),v()):t.key===`Tab`&&Tt(i,t)},b=async i=>{if(i.preventDefault(),!(m||h)){h=!0,f.textContent=``,d.disabled=!0,a.setAttribute(`aria-busy`,`true`);try{if(Y(n),!p){let t=c.value.trim();await J(n,async()=>{await e.auth.sendMagicCode({email:t})}),p=!0,c.readOnly=!0,u.hidden=!1,l.required=!0,o.textContent=`인증 코드`,s.textContent=`${t}로 보낸 코드를 입력하세요.`,d.textContent=`확인`,l.focus();return}await J(n,async()=>{await e.auth.signInWithMagicCode({email:c.value.trim(),code:l.value.trim()})});let r=await J(n,()=>e.getAuth());if(!r)throw Error(`인증 세션을 확인할 수 없습니다.`);_(()=>t(r))}catch(e){if(m||n.aborted||wt(e,`AUTH_CANCELLED`))return;f.textContent=_t(e)}finally{h=!1,!m&&(g||n.aborted)?_(()=>r(Z())):m||(d.disabled=!1,a.removeAttribute(`aria-busy`))}}};n.addEventListener(`abort`,v,{once:!0}),i.addEventListener(`keydown`,y),a.addEventListener(`submit`,b)})}function ht(e,t,n=``,r){if(t.aborted)return Promise.reject(Z());let i=vt(e);i.replaceChildren(yt(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(Z())),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 gt(e,t,n){if(t.aborted)return Promise.reject(Z());let r=vt(e);r.replaceChildren(yt(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(Z())),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)})}function _t(e){if(e&&typeof e==`object`&&`body`in e){let t=e.body;if(t?.message)return t.message}return e instanceof Error?e.message:`로그인에 실패했습니다. 다시 시도해 주세요.`}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=kt,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-login-title`),n.setAttribute(`aria-describedby`,`visual-review-login-description`);let r=X(t,`p`,`01.works`,`eyebrow`),i=X(t,`h2`,`Visual Review`);i.id=`visual-review-login-title`;let a=X(t,`p`,`초대받은 이메일로 계속하세요.`,`description`);a.id=`visual-review-login-description`;let o=t.createElement(`label`);o.append(`이메일`);let s=t.createElement(`input`);s.name=`email`,s.type=`email`,s.autocomplete=`email`,s.required=!0,o.append(s);let c=t.createElement(`label`);c.className=`code`,c.hidden=!0,c.append(`인증 코드`);let l=t.createElement(`input`);l.name=`code`,l.inputMode=`numeric`,l.autocomplete=`one-time-code`,c.append(l);let u=X(t,`p`,``,`error`);u.setAttribute(`role`,`alert`);let d=X(t,`button`,`코드 받기`);return d.type=`submit`,n.append(r,i,a,o,c,u,d),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=X(t,`p`,`01.works`,`eyebrow`),i=X(t,`h2`,`표시 이름`);i.id=`visual-review-name-title`;let a=X(t,`p`,`피드백에 이 이름이 표시됩니다.`,`description`);a.id=`visual-review-name-description`;let o=X(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=X(t,`p`,``,`error`);c.setAttribute(`role`,`alert`);let l=X(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-account-title`),n.setAttribute(`aria-describedby`,`visual-review-account-description`);let r=X(t,`p`,`01.works`,`eyebrow`),i=X(t,`h2`,`계정 확인`);i.id=`visual-review-account-title`;let a=X(t,`p`,`이 초대는 현재 로그인한 계정과 일치하지 않습니다.`,`description`);a.id=`visual-review-account-description`;let o=X(t,`button`,`다른 계정으로 계속`);return o.type=`submit`,n.append(r,i,a,o),n}function X(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 Z(){return new ot(`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-CyJ52cJi.js";import{t}from"./generated-frame-CkUKpj
|
|
|
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
|
-
`;var Q=class extends Error{code;status;constructor(e,t,n){super(t),this.code=e,this.status=n,this.name=`HostedBootstrapError`}};function At(e={}){return jt(e)}function jt(t={},n={}){let r=e(t.serviceUrl??`https://visual-review.01.works`),i=t.fetch??globalThis.fetch,a=n.instantRuntimeFactory??st;if(typeof i!=`function`)throw Error(`Visual Review bootstrap requires the Fetch API`);return{async resolve(e){let t=Mt(e),n=await Pt(r,i,t,e.signal);return a(n.instantAppId,{serviceUrl:r,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 It(t);if(!t.ok)throw new Q($(n,`error`)??`INVITATION_ACCEPT_FAILED`,$(n,`message`)??`리뷰 초대 수락에 실패했습니다.`,t.status)},...e.collaboration?.cursors===!0?{resolveCollaborationRoom:e=>Nt(r,i,e)}:{}}).resolve(e)}}}function Mt(e){return{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname}}async function Nt(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 It(r);if(!r.ok)throw new Q($(i,`error`)??`COLLABORATION_ROOM_FAILED`,$(i,`message`)??`실시간 협업 연결에 실패했습니다.`,r.status);if(!i||typeof i!=`object`||Array.isArray(i))throw new Q(`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 Q(`INVALID_COLLABORATION_ROOM`,`잘못된 협업 응답입니다.`,502);return{id:o,expiresAt:a.expiresAt}}async function Pt(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 It(i);if(!i.ok)throw new Q($(a,`error`)??`BOOTSTRAP_FAILED`,$(a,`message`)??`Visual Review bootstrap에 실패했습니다.`,i.status);return Ft(a)}function Ft(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let t=e,n=$(t,`instantAppId`);if(t.apiVersion!==1||!n||!Lt(n))throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{apiVersion:1,instantAppId:n}}async function It(e){try{return await e.json()}catch{throw new Q(`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 Lt(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{At as createHostedReviewRuntime};
|
|
13
|
+
`;var Q=class extends Error{code;status;constructor(e,t,n){super(t),this.code=e,this.status=n,this.name=`HostedBootstrapError`}};function At(e={}){return jt(e)}function jt(t={},n={}){let r=e(t.serviceUrl??`https://visual-review.01.works`),i=t.fetch??globalThis.fetch,a=n.instantRuntimeFactory??st;if(typeof i!=`function`)throw Error(`Visual Review bootstrap requires the Fetch API`);return{async resolve(e){let t=Mt(e),n=await Pt(r,i,t,e.signal);return a(n.instantAppId,{serviceUrl:r,...n.reviewer?{reviewerToken:n.reviewer.token}:{},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 It(t);if(!t.ok)throw new Q($(n,`error`)??`INVITATION_ACCEPT_FAILED`,$(n,`message`)??`리뷰 초대 수락에 실패했습니다.`,t.status)},...e.collaboration?.cursors===!0?{resolveCollaborationRoom:e=>Nt(r,i,e)}:{}}).resolve(e)}}}function Mt(e){return{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname}}async function Nt(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 It(r);if(!r.ok)throw new Q($(i,`error`)??`COLLABORATION_ROOM_FAILED`,$(i,`message`)??`실시간 협업 연결에 실패했습니다.`,r.status);if(!i||typeof i!=`object`||Array.isArray(i))throw new Q(`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 Q(`INVALID_COLLABORATION_ROOM`,`잘못된 협업 응답입니다.`,502);return{id:o,expiresAt:a.expiresAt}}async function Pt(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 It(i);if(!i.ok)throw new Q($(a,`error`)??`BOOTSTRAP_FAILED`,$(a,`message`)??`Visual Review bootstrap에 실패했습니다.`,i.status);return Ft(a)}function Ft(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let t=e,n=$(t,`instantAppId`);if(t.apiVersion!==1||!n||!Lt(n))throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let r=t.reviewer;if(r==null)return{apiVersion:1,instantAppId:n};let i=$(r,`token`),a=$(r,`email`);if(!i||!a)throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{apiVersion:1,instantAppId:n,reviewer:{token:i,email:a}}}async function It(e){try{return await e.json()}catch{throw new Q(`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 Lt(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{At as createHostedReviewRuntime};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./install-
|
|
1
|
+
import{t as e}from"./install-C-4G_vDp.js";export{e as installVisualReview};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=`https://visual-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;function o(e={}){if(e.enabled!==!0||typeof window>`u`||typeof document>`u`)return n();let r=!1,i=0,a=null,o=null,p=null,h=null,g=document.baseURI,_=new WeakMap,S=new Map,E=W(window),A=Z(e.styleNonce,document),M=e.activationParam??`visual-review`,N=v(window.location,M),P=m(window,e=>{let t=v(e,M);if(t===N)return;let n=D(M,e.href);n&&S.set(e.origin,n),N=t,I()}),F=e=>{r||!p||e.target!==p||(N=v(window.location,M),I())};return window.addEventListener(`visual-review:reauthenticate-required`,F),{ready:I(),refresh(){return r?Promise.resolve(null):(N=v(window.location,M),I())},dispose(){r||(r=!0,i+=1,a?.abort(),a=null,p?.remove(),p=null,h?.remove(),h=null,S.clear(),P.unsubscribe(),window.removeEventListener(`visual-review:reauthenticate-required`,F))}};function I(){let t=++i;a?.abort(),p?.remove(),p=null,h?.remove();let n=new AbortController,r=document.createElement(`div`);r.dataset.agencyReviewRoot=``,a=n,h=r;let s=L(t,n,r);return o=s,s.then(r=>{r&&B(t,n)&&p===r&&e.onReady?.(r)}),s}async function L(t,n,i){try{let e=document.body??await j(document,n.signal);if(!B(t,n))return V(t);e.append(i);let r=await R(t,n,i);return B(t,n)?r:(i.remove(),V(t))}catch(a){if(!B(t,n))return i.remove(),V(t);if(d(a,`AUTH_CANCELLED`))return i.remove(),h===i&&(h=null),null;z(a,i);let o=Y(a,_.get(i)?.[2]);return J(i,o.message,A,()=>{r||h!==i||(N=v(window.location,M),I())}),e.onError?.(o),window.dispatchEvent(new CustomEvent(`visual-review:error`,{detail:o})),null}}async function R(n,r,i){let a=t(e.serviceUrl??`https://visual-review.01.works`),o=y(window.location),d=ee(a,M,o,E),f=b(S.get(o.origin)),m=x(C(a,o.origin)),D=d?.source===`url`?d:f??m??d;if(!D)return _.delete(i),i.remove(),h===i&&(h=null),null;let j=D.invitationId;_.set(i,[a,o.origin,j]),D.source===`url`?(G(a,o.origin,E),S.set(o.origin,j),w(a,o.origin,j),P.suppress(()=>O(M))):D.source===`handoff`&&S.set(o.origin,j),N=v(window.location,M);let F=await k((e.runtime??await c(a)).resolve({invitationId:j,location:o,signal:r.signal,authHost:i,styleNonce:A,collaboration:{cursors:e.collaboration?.cursors===!0,chat:e.collaboration?.chat===!0,scopeId:s(e.build,o)}}),r.signal);if(!B(n,r))return null;T(a,o.origin,j),H(a,j,o,E),S.set(o.origin,j);let I=e.sourceContextResolver??await u(e.build,g,r.signal);if(!B(n,r))return null;let{mountReviewWidget:L}=await l(r.signal);return B(n,r)?(p=L({...F,collaboration:{cursors:e.collaboration?.cursors===!0&&!!(F.collaborationRepository&&F.collaborationRoomId),chat:e.collaboration?.chat===!0&&!!F.collaborationRepository,repository:F.collaborationRepository,roomId:F.collaborationRoomId,scopeId:s(e.build,o)},developerTools:e.developerTools,sourceContextResolver:I,styleNonce:A}),i.remove(),h===i&&(h=null),window.dispatchEvent(new CustomEvent(`visual-review:ready`,{detail:p})),p):null}function z(e,t){if(!f(e))return;let n=_.get(t);if(!n)return;let[r,i,a]=n;T(r,i,a),S.get(i)===a&&S.delete(i),G(r,i,E,a)}function B(e,t){return!r&&i===e&&a===t&&!t.signal.aborted}function V(e){return!r&&i!==e?o:null}}function s(e,t){return JSON.stringify([M(e).buildId,t.pathname,t.search])}async function c(e){let{createHostedReviewRuntime:t}=await import(`./hosted-runtime-CIvL-1-W.js`);return t({serviceUrl:e})}async function l(e){return A(import(`./src-DX1bVKG6.js`),e,a,`리뷰 위젯을 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`)}async function u(e,t,n){let r=M(e),{createGeneratedSourceContextResolver:i}=await A(import(`./generated-source-context-9dbnOHdW.js`),n,a,`리뷰 소스 정보를 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`);return i({build:r,sourceIndexBaseUrl:t})}function d(e,t){return e instanceof Error&&`code`in e&&e.code===t}function f(e){let t=e instanceof Error&&`code`in e?e.code:void 0;return typeof t==`string`&&/^INVITATION_(?:EXPIRED|NOT_FOUND|REQUIRED|REVOKED)$/.test(t)}const p=new WeakMap;function m(e,t){let n=p.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),h(e)},patchedReplaceState:function(t,n,r){i.call(this,t,n,r),h(e)},popstateListener:()=>h(e),subscribers:a,suppressionDepth:0},p.set(e,n),g(t,`pushState`,n.patchedPushState),g(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),_(n.history,`pushState`,n.patchedPushState,n.originalPushStateDescriptor),_(n.history,`replaceState`,n.patchedReplaceState,n.originalReplaceStateDescriptor),p.delete(e)))}}}function h(e){let t=p.get(e);if(!t||t.suppressionDepth>0)return;let n=y(e.location);[...t.subscribers].forEach(e=>e(n))}function g(e,t,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:!0,value:n})}function _(e,t,n,r){if(Object.getOwnPropertyDescriptor(e,t)?.value===n){if(r){Object.defineProperty(e,t,r);return}delete e[t]}}function v(e,t){return`${e.origin}\n${e.pathname}\n${D(t,e.href)??``}`}function y(e){return new URL(e.href)}function b(e){return e?{invitationId:e,source:`memory`}:null}function x(e){return e?{invitationId:e,source:`handoff`}:null}function S(e,t){return JSON.stringify([e,t])}function C(e,t,n=Date.now()){let i=S(e,t),a=r.get(i);if(a){if(a.expiresAt>n)return a.invitationId;clearTimeout(a.timeout),r.delete(i)}}function w(e,t,n,a=Date.now()){E(a);let o=S(e,t),s=r.get(o);for(s&&(clearTimeout(s.timeout),r.delete(o));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 c=a+i,l=setTimeout(()=>{r.get(o)?.expiresAt===c&&r.delete(o)},i);r.set(o,{invitationId:n,expiresAt:c,timeout:l})}function T(e,t,n){let i=S(e,t),a=r.get(i);a?.invitationId===n&&(clearTimeout(a.timeout),r.delete(i))}function E(e){for(let[t,n]of r)n.expiresAt>e||(clearTimeout(n.timeout),r.delete(t))}function ee(e,t,n,r){let i=D(t,n.href);if(i)return{invitationId:i,source:`url`};let a=U(r,K(e,n.origin));return a?{invitationId:a,source:`storage`}:q(n.hostname)?{invitationId:`local-preview`,source:`local-preview`}:null}function D(e,t){let n=new URL(t);return(n.searchParams.get(e)??n.searchParams.get(`agency-review`)??n.searchParams.get(`agency-review-invite`))?.trim()||null}function O(e){let t=new URL(window.location.href),n=new Set([e,`visual-review`,`agency-review`,`agency-review-invite`]),r=!1;n.forEach(e=>{t.searchParams.has(e)&&(t.searchParams.delete(e),r=!0)}),r&&window.history.replaceState(window.history.state,``,`${t.pathname}${t.search}${t.hash}`)}function k(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 A(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 j(e,t){return e.body?Promise.resolve(e.body):t.aborted?Promise.reject(new DOMException(`Aborted`,`AbortError`)):new Promise((n,r)=>{let i=!1,a=new MutationObserver(()=>c()),o=()=>{e.removeEventListener(`DOMContentLoaded`,c),t.removeEventListener(`abort`,l),a.disconnect()},s=e=>{i||(i=!0,o(),e())},c=()=>{let t=e.body;t&&s(()=>n(t))},l=()=>{s(()=>r(new DOMException(`Aborted`,`AbortError`)))};e.addEventListener(`DOMContentLoaded`,c),t.addEventListener(`abort`,l,{once:!0}),a.observe(e,{childList:!0,subtree:!0}),c()})}function M(e){let t=document.querySelector(`meta[name="visual-review-build"]`),n=document.querySelector(`meta[name="visual-review-commit"]`),r=V(F()),i=V(I());return{buildId:B(e?.buildId)??z(t)??r??`unversioned`,gitCommit:L(e,n,i),generatedAt:e?.generatedAt,mode:e?.mode??P(N())??(q(window.location.hostname)?`development`:`production`)}}function N(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_MODE}catch{return}}function P(e){return e===`development`||e===`preview`||e===`production`?e:void 0}function F(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_ID}catch{return}}function I(){try{return process.env.VISUAL_REVIEW_PUBLIC_GIT_COMMIT}catch{return}}function L(e,t,n){return e?.gitCommit===null?null:typeof e?.gitCommit==`string`?R(e.gitCommit):R(t?.content)??R(n)}function R(e){if(typeof e!=`string`)return null;let t=e.trim().toLowerCase();return/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(t)?t:null}function z(e){return V(e?.content)}function B(e){let t=typeof e==`string`?e.trim():``;return t.length>0?t:null}function V(e){return typeof e==`string`&&e.length>0?e:null}function H(e,t,n,r){try{r?.setItem(K(e,n.origin),t)}catch{}}function U(e,t){try{return e?.getItem(t)??null}catch{return null}}function W(e){try{return e.localStorage}catch{return null}}function G(e,t,n,r){try{if(!n)return;let i=K(e,t),a=n.getItem(i);if(a===null||r!==void 0&&a!==r)return;n.removeItem(i)}catch{}}function K(e,t){return`visual-review:${e}:${t}:invitation`}function q(e){return e===`localhost`||e===`127.0.0.1`||e.endsWith(`.test`)||e.endsWith(`.local`)}function J(e,t,n,r){let i=e.shadowRoot??e.attachShadow({mode:`open`}),a=i.ownerDocument,o=a.createElement(`style`);n&&(o.nonce=n),o.textContent=te;let s=a.createElement(`strong`);s.textContent=`Visual Review를 시작할 수 없습니다`;let c=a.createElement(`span`);c.textContent=t;let l=a.createElement(`button`);l.type=`button`,l.textContent=`다시 시도`,l.addEventListener(`click`,()=>{l.disabled=!0,r?.()},{once:!0}),i.replaceChildren(o,s,c,l)}function Y(e,t){let n=e instanceof Error?e.message:String(e),r=Error(X(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:X(n,t)}),typeof i==`number`&&Number.isFinite(i)&&Object.defineProperty(r,"status",{configurable:!0,enumerable:!0,value:i})}return r}function X(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 Z(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}const te=`:host{all:initial;position:fixed;right:18px;bottom:18px;z-index:2147483646;max-width:360px;padding:16px 18px;border:1px solid #efc4bd;border-radius:14px;background:#fff8f6;box-shadow:0 12px 40px rgba(0,0,0,.14);color:#7a271a;font:13px/1.5 Inter,ui-sans-serif,system-ui,sans-serif}strong{display:block;margin-bottom:4px;color:#53150d}span{display:block}button{margin-top:12px;padding:7px 10px;border:1px solid #d9a79f;border-radius:8px;background:#fff;color:#7a271a;font:650 12px/1 Inter,ui-sans-serif,system-ui,sans-serif;cursor:pointer}button:focus-visible{outline:2px solid #7a271a;outline-offset:2px}button:disabled{opacity:.55;cursor:wait}`;export{e as n,t as r,o as t};
|
|
1
|
+
const e=`https://visual-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;function o(e={}){if(e.enabled!==!0||typeof window>`u`||typeof document>`u`)return n();let r=!1,i=0,a=null,o=null,p=null,h=null,g=document.baseURI,_=new WeakMap,S=new Map,E=W(window),A=Z(e.styleNonce,document),M=e.activationParam??`visual-review`,N=v(window.location,M),P=m(window,e=>{let t=v(e,M);if(t===N)return;let n=D(M,e.href);n&&S.set(e.origin,n),N=t,I()}),F=e=>{r||!p||e.target!==p||(N=v(window.location,M),I())};return window.addEventListener(`visual-review:reauthenticate-required`,F),{ready:I(),refresh(){return r?Promise.resolve(null):(N=v(window.location,M),I())},dispose(){r||(r=!0,i+=1,a?.abort(),a=null,p?.remove(),p=null,h?.remove(),h=null,S.clear(),P.unsubscribe(),window.removeEventListener(`visual-review:reauthenticate-required`,F))}};function I(){let t=++i;a?.abort(),p?.remove(),p=null,h?.remove();let n=new AbortController,r=document.createElement(`div`);r.dataset.agencyReviewRoot=``,a=n,h=r;let s=L(t,n,r);return o=s,s.then(r=>{r&&B(t,n)&&p===r&&e.onReady?.(r)}),s}async function L(t,n,i){try{let e=document.body??await j(document,n.signal);if(!B(t,n))return V(t);e.append(i);let r=await R(t,n,i);return B(t,n)?r:(i.remove(),V(t))}catch(a){if(!B(t,n))return i.remove(),V(t);if(d(a,`AUTH_CANCELLED`))return i.remove(),h===i&&(h=null),null;z(a,i);let o=Y(a,_.get(i)?.[2]);return J(i,o.message,A,()=>{r||h!==i||(N=v(window.location,M),I())}),e.onError?.(o),window.dispatchEvent(new CustomEvent(`visual-review:error`,{detail:o})),null}}async function R(n,r,i){let a=t(e.serviceUrl??`https://visual-review.01.works`),o=y(window.location),d=ee(a,M,o,E),f=b(S.get(o.origin)),m=x(C(a,o.origin)),D=d?.source===`url`?d:f??m??d;if(!D)return _.delete(i),i.remove(),h===i&&(h=null),null;let j=D.invitationId;_.set(i,[a,o.origin,j]),D.source===`url`?(G(a,o.origin,E),S.set(o.origin,j),w(a,o.origin,j),P.suppress(()=>O(M))):D.source===`handoff`&&S.set(o.origin,j),N=v(window.location,M);let F=await k((e.runtime??await c(a)).resolve({invitationId:j,location:o,signal:r.signal,authHost:i,styleNonce:A,collaboration:{cursors:e.collaboration?.cursors===!0,chat:e.collaboration?.chat===!0,scopeId:s(e.build,o)}}),r.signal);if(!B(n,r))return null;T(a,o.origin,j),H(a,j,o,E),S.set(o.origin,j);let I=e.sourceContextResolver??await u(e.build,g,r.signal);if(!B(n,r))return null;let{mountReviewWidget:L}=await l(r.signal);return B(n,r)?(p=L({...F,collaboration:{cursors:e.collaboration?.cursors===!0&&!!(F.collaborationRepository&&F.collaborationRoomId),chat:e.collaboration?.chat===!0&&!!F.collaborationRepository,repository:F.collaborationRepository,roomId:F.collaborationRoomId,scopeId:s(e.build,o)},developerTools:e.developerTools,sourceContextResolver:I,styleNonce:A}),i.remove(),h===i&&(h=null),window.dispatchEvent(new CustomEvent(`visual-review:ready`,{detail:p})),p):null}function z(e,t){if(!f(e))return;let n=_.get(t);if(!n)return;let[r,i,a]=n;T(r,i,a),S.get(i)===a&&S.delete(i),G(r,i,E,a)}function B(e,t){return!r&&i===e&&a===t&&!t.signal.aborted}function V(e){return!r&&i!==e?o:null}}function s(e,t){return JSON.stringify([M(e).buildId,t.pathname,t.search])}async function c(e){let{createHostedReviewRuntime:t}=await import(`./hosted-runtime-1mdUKkOV.js`);return t({serviceUrl:e})}async function l(e){return A(import(`./src-DX1bVKG6.js`),e,a,`리뷰 위젯을 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`)}async function u(e,t,n){let r=M(e),{createGeneratedSourceContextResolver:i}=await A(import(`./generated-source-context-C6kocvPg.js`),n,a,`리뷰 소스 정보를 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`);return i({build:r,sourceIndexBaseUrl:t})}function d(e,t){return e instanceof Error&&`code`in e&&e.code===t}function f(e){let t=e instanceof Error&&`code`in e?e.code:void 0;return typeof t==`string`&&/^INVITATION_(?:EXPIRED|NOT_FOUND|REQUIRED|REVOKED)$/.test(t)}const p=new WeakMap;function m(e,t){let n=p.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),h(e)},patchedReplaceState:function(t,n,r){i.call(this,t,n,r),h(e)},popstateListener:()=>h(e),subscribers:a,suppressionDepth:0},p.set(e,n),g(t,`pushState`,n.patchedPushState),g(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),_(n.history,`pushState`,n.patchedPushState,n.originalPushStateDescriptor),_(n.history,`replaceState`,n.patchedReplaceState,n.originalReplaceStateDescriptor),p.delete(e)))}}}function h(e){let t=p.get(e);if(!t||t.suppressionDepth>0)return;let n=y(e.location);[...t.subscribers].forEach(e=>e(n))}function g(e,t,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:!0,value:n})}function _(e,t,n,r){if(Object.getOwnPropertyDescriptor(e,t)?.value===n){if(r){Object.defineProperty(e,t,r);return}delete e[t]}}function v(e,t){return`${e.origin}\n${e.pathname}\n${D(t,e.href)??``}`}function y(e){return new URL(e.href)}function b(e){return e?{invitationId:e,source:`memory`}:null}function x(e){return e?{invitationId:e,source:`handoff`}:null}function S(e,t){return JSON.stringify([e,t])}function C(e,t,n=Date.now()){let i=S(e,t),a=r.get(i);if(a){if(a.expiresAt>n)return a.invitationId;clearTimeout(a.timeout),r.delete(i)}}function w(e,t,n,a=Date.now()){E(a);let o=S(e,t),s=r.get(o);for(s&&(clearTimeout(s.timeout),r.delete(o));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 c=a+i,l=setTimeout(()=>{r.get(o)?.expiresAt===c&&r.delete(o)},i);r.set(o,{invitationId:n,expiresAt:c,timeout:l})}function T(e,t,n){let i=S(e,t),a=r.get(i);a?.invitationId===n&&(clearTimeout(a.timeout),r.delete(i))}function E(e){for(let[t,n]of r)n.expiresAt>e||(clearTimeout(n.timeout),r.delete(t))}function ee(e,t,n,r){let i=D(t,n.href);if(i)return{invitationId:i,source:`url`};let a=U(r,K(e,n.origin));return a?{invitationId:a,source:`storage`}:q(n.hostname)?{invitationId:`local-preview`,source:`local-preview`}:null}function D(e,t){let n=new URL(t);return(n.searchParams.get(e)??n.searchParams.get(`agency-review`)??n.searchParams.get(`agency-review-invite`))?.trim()||null}function O(e){let t=new URL(window.location.href),n=new Set([e,`visual-review`,`agency-review`,`agency-review-invite`]),r=!1;n.forEach(e=>{t.searchParams.has(e)&&(t.searchParams.delete(e),r=!0)}),r&&window.history.replaceState(window.history.state,``,`${t.pathname}${t.search}${t.hash}`)}function k(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 A(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 j(e,t){return e.body?Promise.resolve(e.body):t.aborted?Promise.reject(new DOMException(`Aborted`,`AbortError`)):new Promise((n,r)=>{let i=!1,a=new MutationObserver(()=>c()),o=()=>{e.removeEventListener(`DOMContentLoaded`,c),t.removeEventListener(`abort`,l),a.disconnect()},s=e=>{i||(i=!0,o(),e())},c=()=>{let t=e.body;t&&s(()=>n(t))},l=()=>{s(()=>r(new DOMException(`Aborted`,`AbortError`)))};e.addEventListener(`DOMContentLoaded`,c),t.addEventListener(`abort`,l,{once:!0}),a.observe(e,{childList:!0,subtree:!0}),c()})}function M(e){let t=document.querySelector(`meta[name="visual-review-build"]`),n=document.querySelector(`meta[name="visual-review-commit"]`),r=V(F()),i=V(I());return{buildId:B(e?.buildId)??z(t)??r??`unversioned`,gitCommit:L(e,n,i),generatedAt:e?.generatedAt,mode:e?.mode??P(N())??(q(window.location.hostname)?`development`:`production`)}}function N(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_MODE}catch{return}}function P(e){return e===`development`||e===`preview`||e===`production`?e:void 0}function F(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_ID}catch{return}}function I(){try{return process.env.VISUAL_REVIEW_PUBLIC_GIT_COMMIT}catch{return}}function L(e,t,n){return e?.gitCommit===null?null:typeof e?.gitCommit==`string`?R(e.gitCommit):R(t?.content)??R(n)}function R(e){if(typeof e!=`string`)return null;let t=e.trim().toLowerCase();return/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(t)?t:null}function z(e){return V(e?.content)}function B(e){let t=typeof e==`string`?e.trim():``;return t.length>0?t:null}function V(e){return typeof e==`string`&&e.length>0?e:null}function H(e,t,n,r){try{r?.setItem(K(e,n.origin),t)}catch{}}function U(e,t){try{return e?.getItem(t)??null}catch{return null}}function W(e){try{return e.localStorage}catch{return null}}function G(e,t,n,r){try{if(!n)return;let i=K(e,t),a=n.getItem(i);if(a===null||r!==void 0&&a!==r)return;n.removeItem(i)}catch{}}function K(e,t){return`visual-review:${e}:${t}:invitation`}function q(e){return e===`localhost`||e===`127.0.0.1`||e.endsWith(`.test`)||e.endsWith(`.local`)}function J(e,t,n,r){let i=e.shadowRoot??e.attachShadow({mode:`open`}),a=i.ownerDocument,o=a.createElement(`style`);n&&(o.nonce=n),o.textContent=te;let s=a.createElement(`strong`);s.textContent=`Visual Review를 시작할 수 없습니다`;let c=a.createElement(`span`);c.textContent=t;let l=a.createElement(`button`);l.type=`button`,l.textContent=`다시 시도`,l.addEventListener(`click`,()=>{l.disabled=!0,r?.()},{once:!0}),i.replaceChildren(o,s,c,l)}function Y(e,t){let n=e instanceof Error?e.message:String(e),r=Error(X(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:X(n,t)}),typeof i==`number`&&Number.isFinite(i)&&Object.defineProperty(r,"status",{configurable:!0,enumerable:!0,value:i})}return r}function X(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 Z(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}const te=`:host{all:initial;position:fixed;right:18px;bottom:18px;z-index:2147483646;max-width:360px;padding:16px 18px;border:1px solid #efc4bd;border-radius:14px;background:#fff8f6;box-shadow:0 12px 40px rgba(0,0,0,.14);color:#7a271a;font:13px/1.5 Inter,ui-sans-serif,system-ui,sans-serif}strong{display:block;margin-bottom:4px;color:#53150d}span{display:block}button{margin-top:12px;padding:7px 10px;border:1px solid #d9a79f;border-radius:8px;background:#fff;color:#7a271a;font:650 12px/1 Inter,ui-sans-serif,system-ui,sans-serif;cursor:pointer}button:focus-visible{outline:2px solid #7a271a;outline-offset:2px}button:disabled{opacity:.55;cursor:wait}`;export{e as n,t as r,o as t};
|
package/dist/next-config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as resolveVisualReviewBuildIdentity } from "./build-identity-CgoY3-jy.js";
|
|
2
|
-
import { a as
|
|
2
|
+
import { a as nextSourceIndexUrl, d as cleanupNextSourceMapOutput, f as uploadNextSourceMaps, l as writeNextVisualReviewSourceIndex, o as visualReviewSourceIndexFilename } from "./source-index-o5fwJzns.js";
|
|
3
3
|
import { randomBytes } from "node:crypto";
|
|
4
4
|
import { dirname, join, resolve } from "node:path";
|
|
5
5
|
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -92,7 +92,11 @@ function withVisualReview(nextConfig = {}, options = {}) {
|
|
|
92
92
|
const identity = resolveNextVisualReviewBuildIdentity(options, process.env);
|
|
93
93
|
const sourceMapUpload = resolveSourceMapUpload(options.sourceMaps, process.env);
|
|
94
94
|
const sourceMetadataEnabled = options.sourceMetadata ?? true;
|
|
95
|
-
const
|
|
95
|
+
const sourceMetadataOptions = {
|
|
96
|
+
enabled: sourceMetadataEnabled,
|
|
97
|
+
embedSourcePath: options.embedSourcePath ?? true,
|
|
98
|
+
markerSalt: sourceMetadataEnabled ? resolveBuildLocalMarkerSalt(process.env) : void 0
|
|
99
|
+
};
|
|
96
100
|
const injected = {
|
|
97
101
|
[BUILD_ID_LITERAL]: identity.buildId,
|
|
98
102
|
[GIT_COMMIT_LITERAL]: identity.gitCommit ?? "",
|
|
@@ -100,11 +104,11 @@ function withVisualReview(nextConfig = {}, options = {}) {
|
|
|
100
104
|
};
|
|
101
105
|
if (typeof nextConfig === "function") return function visualReviewNextConfig(...arguments_) {
|
|
102
106
|
const resolved = nextConfig.apply(this, arguments_);
|
|
103
|
-
return isPromiseLike(resolved) ? resolved.then((config) => configureNext(config, injected, identity, sourceMapUpload,
|
|
107
|
+
return isPromiseLike(resolved) ? resolved.then((config) => configureNext(config, injected, identity, sourceMapUpload, sourceMetadataOptions)) : configureNext(resolved, injected, identity, sourceMapUpload, sourceMetadataOptions);
|
|
104
108
|
};
|
|
105
|
-
return configureNext(nextConfig, injected, identity, sourceMapUpload,
|
|
109
|
+
return configureNext(nextConfig, injected, identity, sourceMapUpload, sourceMetadataOptions);
|
|
106
110
|
}
|
|
107
|
-
function configureNext(nextConfig, injected, identity, sourceMapUpload,
|
|
111
|
+
function configureNext(nextConfig, injected, identity, sourceMapUpload, sourceMetadataOptions) {
|
|
108
112
|
const previousHookMetadata = getVisualReviewHookMetadata(nextConfig.compiler?.runAfterProductionCompile);
|
|
109
113
|
const previouslyWrapped = isVisualReviewConfig(nextConfig) || previousHookMetadata !== void 0;
|
|
110
114
|
assertReservedLiterals(nextConfig.env, injected, previouslyWrapped);
|
|
@@ -116,11 +120,11 @@ function configureNext(nextConfig, injected, identity, sourceMapUpload, sourceMe
|
|
|
116
120
|
}
|
|
117
121
|
};
|
|
118
122
|
if (previousHookMetadata) configured = restoreSourceMapConfiguration(configured, previousHookMetadata);
|
|
119
|
-
if (!sourceMapUpload && !
|
|
123
|
+
if (!sourceMapUpload && !sourceMetadataOptions.enabled) return markVisualReviewConfig(configured);
|
|
120
124
|
const hookMetadata = previousHookMetadata ?? captureHookMetadata(nextConfig);
|
|
121
125
|
if (sourceMapUpload && (nextConfig.productionBrowserSourceMaps === false || hookMetadata.productionBrowserSourceMaps.present && hookMetadata.productionBrowserSourceMaps.value === false)) throw new Error("Next productionBrowserSourceMaps=false conflicts with Visual Review source-map upload");
|
|
122
126
|
if (sourceMapUpload && (nextConfig.experimental?.serverSourceMaps === false || hookMetadata.serverSourceMaps.present && hookMetadata.serverSourceMaps.value === false)) throw new Error("Next experimental.serverSourceMaps=false conflicts with Visual Review source-map upload");
|
|
123
|
-
const sourceMetadata =
|
|
127
|
+
const sourceMetadata = sourceMetadataOptions.enabled ? resolveNextSourceMetadata(identity, nextConfig.basePath, sourceMetadataOptions.markerSalt, sourceMetadataOptions.embedSourcePath) : void 0;
|
|
124
128
|
const sourceConfigured = sourceMetadata ? configureNextSourceMetadata(configured, hookMetadata, sourceMetadata) : configured;
|
|
125
129
|
const compiler = sourceConfigured.compiler ?? {};
|
|
126
130
|
return markVisualReviewConfig({
|
|
@@ -150,7 +154,7 @@ function composeProductionCompileHook(existingHook, identity, sourceMapUpload, s
|
|
|
150
154
|
}
|
|
151
155
|
throw existingError;
|
|
152
156
|
}
|
|
153
|
-
if (sourceMetadata) try {
|
|
157
|
+
if (sourceMetadata && !sourceMetadata.embedSourcePath) try {
|
|
154
158
|
await writeNextVisualReviewSourceIndex({
|
|
155
159
|
projectDir: metadata.projectDir,
|
|
156
160
|
distDir: metadata.distDir,
|
|
@@ -226,11 +230,12 @@ function restoreProperty(target, key, state) {
|
|
|
226
230
|
if (state.present) target[key] = state.value;
|
|
227
231
|
else delete target[key];
|
|
228
232
|
}
|
|
229
|
-
function resolveNextSourceMetadata(identity, basePath, markerSalt) {
|
|
233
|
+
function resolveNextSourceMetadata(identity, basePath, markerSalt, embedSourcePath) {
|
|
230
234
|
if (!markerSalt) throw new Error("Visual Review source marker salt is unavailable");
|
|
231
235
|
const filename = visualReviewSourceIndexFilename(identity.buildId, markerSalt.salt);
|
|
232
236
|
const loaderUrl = new URL("./source-loader.js", import.meta.url);
|
|
233
237
|
return {
|
|
238
|
+
embedSourcePath,
|
|
234
239
|
filename,
|
|
235
240
|
indexUrl: nextSourceIndexUrl(basePath, filename),
|
|
236
241
|
loader: loaderUrl.protocol === "file:" ? fileURLToPath(loaderUrl) : resolve(process.cwd(), "packages/review-client/dist/source-loader.js"),
|
|
@@ -319,6 +324,7 @@ function appendWebpackRule(existing, sourceMetadata) {
|
|
|
319
324
|
use: [{
|
|
320
325
|
loader: sourceMetadata.loader,
|
|
321
326
|
options: {
|
|
327
|
+
embedSourcePath: sourceMetadata.embedSourcePath,
|
|
322
328
|
indexUrl: sourceMetadata.indexUrl,
|
|
323
329
|
saltPath: sourceMetadata.saltPath
|
|
324
330
|
}
|
|
@@ -343,6 +349,7 @@ function appendTurbopackRules(existing, sourceMetadata) {
|
|
|
343
349
|
loader: sourceMetadata.loader,
|
|
344
350
|
options: {
|
|
345
351
|
compile: true,
|
|
352
|
+
embedSourcePath: sourceMetadata.embedSourcePath,
|
|
346
353
|
indexUrl: sourceMetadata.indexUrl,
|
|
347
354
|
saltPath: sourceMetadata.saltPath
|
|
348
355
|
}
|
package/dist/react.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./install-
|
|
1
|
+
import{t as e}from"./install-C-4G_vDp.js";import{useEffect as t,useRef as n}from"react";function r({activationParam:r,build:i,collaboration:a,developerTools:o,enabled:s,onError:c,onReady:l,runtime:u,serviceUrl:d,sourceContextResolver:f,styleNonce:p}){let m=n(c),h=n(l),g=i?.buildId,_=i?.gitCommit,v=i?.generatedAt,y=i?.mode,b=o?.reactGrab===!0,x=a?.cursors===!0,S=a?.chat===!0;return m.current=c,h.current=l,t(()=>{if(s!==!0)return;let t=e({activationParam:r,build:g===void 0&&_===void 0&&v===void 0&&y===void 0?void 0:{buildId:g,gitCommit:_,generatedAt:v,mode:y},collaboration:x||S?{cursors:x,chat:S}:void 0,developerTools:b?{reactGrab:!0}:void 0,enabled:s,onError:e=>m.current?.(e),onReady:e=>h.current?.(e),runtime:u,serviceUrl:d,sourceContextResolver:f,styleNonce:p});return()=>t.dispose()},[r,g,y,S,x,b,s,v,_,u,d,f,p]),null}r.displayName=`VisualReview`;export{r as VisualReview};
|
|
@@ -1041,6 +1041,8 @@ function isNodeError$1(value) {
|
|
|
1041
1041
|
const VISUAL_REVIEW_SOURCE_MARKER_ATTRIBUTE = "data-visual-review-source";
|
|
1042
1042
|
const VISUAL_REVIEW_SOURCE_COORDINATE_ATTRIBUTE = "data-visual-review-source-coordinate";
|
|
1043
1043
|
const VISUAL_REVIEW_SOURCE_INDEX_ATTRIBUTE = "data-visual-review-source-index";
|
|
1044
|
+
/** Plain `path:line:column`, read directly by the capture with no index or symbolication. */
|
|
1045
|
+
const VISUAL_REVIEW_EMBEDDED_SOURCE_ATTRIBUTE = "data-review-source";
|
|
1044
1046
|
const SOURCE_MARKER_PREFIX = "vr1_";
|
|
1045
1047
|
const SOURCE_COORDINATE_PATTERN = /vrc1_([0-9a-f]{32})/gu;
|
|
1046
1048
|
const SOURCE_INDEX_FILENAME_PATTERN = /^visual-review-sources-[0-9a-f]{16}\.json$/u;
|
|
@@ -1395,4 +1397,4 @@ function assertInside(root, path) {
|
|
|
1395
1397
|
if (!candidate || candidate === ".." || candidate.startsWith(`..${sep}`) || isAbsolute(candidate)) throw new Error("Visual Review source index escaped the build output");
|
|
1396
1398
|
}
|
|
1397
1399
|
//#endregion
|
|
1398
|
-
export {
|
|
1400
|
+
export { nextSourceIndexUrl as a, viteSourceIndexUrl as c, cleanupNextSourceMapOutput as d, uploadNextSourceMaps as f, VISUAL_REVIEW_SOURCE_MARKER_ATTRIBUTE as i, writeNextVisualReviewSourceIndex as l, uploadViteSourceMaps as m, VISUAL_REVIEW_SOURCE_COORDINATE_ATTRIBUTE as n, visualReviewSourceIndexFilename as o, cleanupViteSourceMapOutput as p, VISUAL_REVIEW_SOURCE_INDEX_ATTRIBUTE as r, visualReviewSourceMarker as s, VISUAL_REVIEW_EMBEDDED_SOURCE_ATTRIBUTE as t, writeViteVisualReviewSourceIndex as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as VISUAL_REVIEW_SOURCE_MARKER_ATTRIBUTE, n as VISUAL_REVIEW_SOURCE_COORDINATE_ATTRIBUTE, r as VISUAL_REVIEW_SOURCE_INDEX_ATTRIBUTE, s as visualReviewSourceMarker, t as VISUAL_REVIEW_EMBEDDED_SOURCE_ATTRIBUTE } from "./source-index-o5fwJzns.js";
|
|
2
2
|
import { createHmac } from "node:crypto";
|
|
3
3
|
import path, { win32 } from "node:path";
|
|
4
4
|
import { parse } from "@babel/parser";
|
|
@@ -47,8 +47,8 @@ function instrumentVisualReviewSource(source, options) {
|
|
|
47
47
|
const coordinate = `vrc1_${digest}`;
|
|
48
48
|
const closingWidth = candidate.selfClosing ? 2 : 1;
|
|
49
49
|
const insertionPoint = candidate.end - closingWidth;
|
|
50
|
-
const metadata = ` ${VISUAL_REVIEW_SOURCE_MARKER_ATTRIBUTE}="${marker}" ${VISUAL_REVIEW_SOURCE_INDEX_ATTRIBUTE}="${options.indexUrl}"`;
|
|
51
|
-
edits.overwrite(candidate.start, candidate.nameEnd, `${source.slice(candidate.start, candidate.nameEnd)} ${VISUAL_REVIEW_SOURCE_COORDINATE_ATTRIBUTE}="${coordinate}"`);
|
|
50
|
+
const metadata = options.embedSourcePath ? ` ${VISUAL_REVIEW_EMBEDDED_SOURCE_ATTRIBUTE}="${escapeAttribute(`${sourcePath}:${line1}:${column1}`)}"` : ` ${VISUAL_REVIEW_SOURCE_MARKER_ATTRIBUTE}="${marker}" ${VISUAL_REVIEW_SOURCE_INDEX_ATTRIBUTE}="${options.indexUrl}"`;
|
|
51
|
+
if (!options.embedSourcePath) edits.overwrite(candidate.start, candidate.nameEnd, `${source.slice(candidate.start, candidate.nameEnd)} ${VISUAL_REVIEW_SOURCE_COORDINATE_ATTRIBUTE}="${coordinate}"`);
|
|
52
52
|
edits.appendLeft(insertionPoint, metadata);
|
|
53
53
|
markerCount += 1;
|
|
54
54
|
}
|
|
@@ -63,6 +63,13 @@ function instrumentVisualReviewSource(source, options) {
|
|
|
63
63
|
markerCount
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Source paths are project-relative and already validated, but an attribute
|
|
68
|
+
* value still has to survive being written into HTML.
|
|
69
|
+
*/
|
|
70
|
+
function escapeAttribute(value) {
|
|
71
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
72
|
+
}
|
|
66
73
|
function assertMarkerSalt(value) {
|
|
67
74
|
if (!MARKER_SALT.test(value)) throw new Error("Visual Review source marker salt must be a lowercase 32-byte hex secret");
|
|
68
75
|
}
|
package/dist/source-loader.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as isVisualReviewProjectSource, t as instrumentVisualReviewSource } from "./source-instrumentation-transform-
|
|
1
|
+
import { n as isVisualReviewProjectSource, t as instrumentVisualReviewSource } from "./source-instrumentation-transform-Cx8SIIWh.js";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { transformSync } from "@babel/core";
|
|
4
4
|
import transformReactJsx from "@babel/plugin-transform-react-jsx";
|
|
@@ -37,7 +37,8 @@ function visualReviewSourceLoader(source, inputMap) {
|
|
|
37
37
|
id: this.resourcePath,
|
|
38
38
|
indexUrl: options.indexUrl,
|
|
39
39
|
markerSalt: options.markerSalt,
|
|
40
|
-
projectRoot
|
|
40
|
+
projectRoot,
|
|
41
|
+
embedSourcePath: options.embedSourcePath
|
|
41
42
|
});
|
|
42
43
|
const code = transformed?.code ?? source;
|
|
43
44
|
const map = transformed?.map ?? inputMap;
|
|
@@ -114,10 +115,12 @@ function parseOptions(value) {
|
|
|
114
115
|
const options = value;
|
|
115
116
|
if (typeof options.indexUrl !== "string" || !options.indexUrl.startsWith("/") || options.indexUrl.startsWith("//") || options.indexUrl.includes("\\")) throw new Error("Visual Review source loader index URL is invalid");
|
|
116
117
|
if (options.projectRoot !== void 0 && typeof options.projectRoot !== "string") throw new Error("Visual Review source loader project root is invalid");
|
|
118
|
+
if (options.embedSourcePath !== void 0 && typeof options.embedSourcePath !== "boolean") throw new Error("Visual Review source loader embedSourcePath is invalid");
|
|
117
119
|
const markerSalt = typeof options.saltPath === "string" ? readMarkerSaltFile(options.saltPath) : options.markerSalt;
|
|
118
120
|
if (typeof markerSalt !== "string" || !MARKER_SALT.test(markerSalt)) throw new Error("Visual Review source loader marker salt is invalid");
|
|
119
121
|
return {
|
|
120
122
|
...options.compile === true ? { compile: true } : {},
|
|
123
|
+
embedSourcePath: options.embedSourcePath ?? true,
|
|
121
124
|
indexUrl: options.indexUrl,
|
|
122
125
|
markerSalt,
|
|
123
126
|
...typeof options.projectRoot === "string" ? { projectRoot: options.projectRoot } : {}
|
package/dist/vite.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as resolveVisualReviewBuildIdentity } from "./build-identity-CgoY3-jy.js";
|
|
2
|
-
import {
|
|
3
|
-
import { t as instrumentVisualReviewSource } from "./source-instrumentation-transform-
|
|
2
|
+
import { c as viteSourceIndexUrl, m as uploadViteSourceMaps, o as visualReviewSourceIndexFilename, p as cleanupViteSourceMapOutput, u as writeViteVisualReviewSourceIndex } from "./source-index-o5fwJzns.js";
|
|
3
|
+
import { t as instrumentVisualReviewSource } from "./source-instrumentation-transform-Cx8SIIWh.js";
|
|
4
4
|
import { randomBytes } from "node:crypto";
|
|
5
5
|
import { resolve } from "node:path";
|
|
6
6
|
//#region src/vite.ts
|
|
@@ -13,10 +13,12 @@ function visualReview(options = {}) {
|
|
|
13
13
|
let resolvedConfig;
|
|
14
14
|
let sourceMapUpload;
|
|
15
15
|
let sourceMetadataEnabled = false;
|
|
16
|
+
let embedSourcePath = true;
|
|
16
17
|
let sourceIndexFilename;
|
|
17
18
|
let sourceIndexUrl;
|
|
18
19
|
let sourceMarkerSalt;
|
|
19
20
|
let releaseMode;
|
|
21
|
+
let serving = false;
|
|
20
22
|
return {
|
|
21
23
|
name: "01works:visual-review-build-identity",
|
|
22
24
|
enforce: "pre",
|
|
@@ -30,12 +32,15 @@ function visualReview(options = {}) {
|
|
|
30
32
|
assertReservedLiterals(config.define, define, "Vite define");
|
|
31
33
|
if (environment?.command === "serve") {
|
|
32
34
|
sourceMapUpload = void 0;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
serving = true;
|
|
36
|
+
embedSourcePath = options.embedSourcePath ?? true;
|
|
37
|
+
sourceMetadataEnabled = (options.sourceMetadata ?? true) && embedSourcePath;
|
|
38
|
+
sourceMarkerSalt = sourceMetadataEnabled ? randomBytes(32).toString("hex") : void 0;
|
|
35
39
|
return { define };
|
|
36
40
|
}
|
|
37
41
|
sourceMapUpload = resolveSourceMapUpload(options.sourceMaps, process.env);
|
|
38
42
|
sourceMetadataEnabled = options.sourceMetadata ?? true;
|
|
43
|
+
embedSourcePath = options.embedSourcePath ?? true;
|
|
39
44
|
sourceMarkerSalt = sourceMetadataEnabled ? randomBytes(32).toString("hex") : void 0;
|
|
40
45
|
if (!sourceMapUpload) return { define };
|
|
41
46
|
if (config.build?.sourcemap === "inline") throw new Error("Visual Review source-map upload refuses inline Vite source maps");
|
|
@@ -63,7 +68,8 @@ function visualReview(options = {}) {
|
|
|
63
68
|
id,
|
|
64
69
|
indexUrl: sourceIndexUrl,
|
|
65
70
|
markerSalt: sourceMarkerSalt,
|
|
66
|
-
projectRoot: resolvedConfig.root
|
|
71
|
+
projectRoot: resolvedConfig.root,
|
|
72
|
+
embedSourcePath
|
|
67
73
|
});
|
|
68
74
|
return transformed ? {
|
|
69
75
|
code: transformed.code,
|
|
@@ -71,9 +77,10 @@ function visualReview(options = {}) {
|
|
|
71
77
|
} : null;
|
|
72
78
|
},
|
|
73
79
|
async closeBundle() {
|
|
80
|
+
if (serving) return;
|
|
74
81
|
if (!identity || !resolvedConfig) throw new Error("Visual Review build adapter was not initialized by Vite");
|
|
75
82
|
const outDir = resolve(resolvedConfig.root, resolvedConfig.build.outDir);
|
|
76
|
-
if (sourceMetadataEnabled) {
|
|
83
|
+
if (sourceMetadataEnabled && !embedSourcePath) {
|
|
77
84
|
if (!sourceIndexFilename) throw new Error("Visual Review source metadata was not initialized by Vite");
|
|
78
85
|
try {
|
|
79
86
|
await writeViteVisualReviewSourceIndex({
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./generated-frame-CkUKpj5U.js";function t(e){let t=new Map,r=e.sourceIndexBaseUrl;return{unavailableProvenance:()=>f(e,`unavailable`),async resolve(i,a){let o=a?.signal;p(o);let s=i.closest(`[data-visual-review-source]`),c=s?await n(s,t,o,r):null;return p(o),{source:c,componentStack:c?[c]:[],provenance:f(e,c?`fallback`:`unavailable`)}}}}async function n(e,t,n,i){let o=e.getAttribute(`data-visual-review-source`),c=e.getAttribute(`data-visual-review-source-index`);if(!o||!/^vr1_[0-9a-f]{32}$/u.test(o)||!c)return null;let l=r(c,e.ownerDocument,i);if(!l||typeof globalThis.fetch!=`function`)return null;let d=t.get(l);if(!d){if(t.size>=v)return null;d=a(l),t.set(l,d)}let f;try{f=await m(d,n)}catch{return null}let p=s(f,o);return p?u(p):null}function r(e,t,n){if(e.length>2048||e.trim()!==e||e.includes(`\\`)||/[\u0000-\u001f\u007f\u202a-\u202e\u2066-\u2069]/u.test(e))return null;try{let r=new URL(e,n??t.baseURI);return r.origin!==t.location.origin||r.username||r.password||r.search||r.hash||!i(r.pathname)?null:r.href}catch{return null}}function i(e){return x.test(e)||S.test(e)}async function a(e){let t=await globalThis.fetch(e,{cache:`force-cache`,credentials:`same-origin`});if(!t.ok)throw Error(`Visual Review source index returned HTTP ${t.status}`);let n=t.headers.get(`content-length`),r=n===null?null:Number(n);if(r!==null&&(!Number.isSafeInteger(r)||r<0||r>_))throw Error(`Visual Review source index exceeds 8 MiB`);let i=await o(t);return JSON.parse(i)}async function o(e){let t=e.body?.getReader();if(!t)return``;let n=new TextDecoder(`utf-8`,{fatal:!0}),r=[],i=0;try{for(;;){let{done:e,value:a}=await t.read();if(e)break;if(i+=a.byteLength,i>_)throw await t.cancel(`Visual Review source index exceeds 8 MiB`),Error(`Visual Review source index exceeds 8 MiB`);r.push(n.decode(a,{stream:!0}))}return r.push(n.decode()),r.join(``)}finally{t.releaseLock()}}function s(t,n){if(!l(t)||t.schemaVersion!==1||!l(t.entries))return;let r=t.entries[n];if(!(!Array.isArray(r)||r.length===0||r.length>y))for(let t of r){if(!l(t)||!c(t.runtime))continue;let n=e(t.assetPath),r=d(t.line1,1,h),i=d(t.column0,0,g);if(!(!n||r===null||i===null))return{assetPath:n,line1:r,column0:i,runtime:t.runtime}}}function c(e){return e===`browser`||e===`server-node`||e===`server-edge`}function l(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function u(e){return{filePath:e.assetPath,lineNumber:e.line1,columnNumber:e.column0+1,componentName:null,origin:`generated`,generated:e}}function d(e,t,n){return typeof e==`number`&&Number.isSafeInteger(e)&&e>=t&&e<=n?e:null}function f(e,t){return{provider:`embedded`,build:e.build,resolvedAt:e.now?.()??Date.now(),sourceMapStatus:t}}function p(e){if(e?.aborted)throw e.reason??Error(`Source context resolution aborted`)}function m(e,t){return t?t.aborted?Promise.reject(t.reason??Error(`Source context resolution aborted`)):new Promise((n,r)=>{let i=()=>r(t.reason??Error(`Source context resolution aborted`));t.addEventListener(`abort`,i,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})}):e}const h=1e7,g=1e7,_=8*1024*1024,v=16,y=64,b=`visual-review-sources-[0-9a-f]{16}\\.json`,x=RegExp(`^/(?:[^/]+/)*\\.visual-review/${b}$`,`u`),S=RegExp(`^/(?:[^/]+/)*_next/static/${b}$`,`u`);export{t as createGeneratedSourceContextResolver};
|