@designfever/web-review-kit 0.7.3 → 0.8.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/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { L as LocalAdapterOptions, W as WebReviewKitAdapter, S as SupabaseReviewAdapterOptions, R as ReviewWorkflowStatus, a as ReviewItemStatus, b as WebReviewKitOptions, c as WebReviewKitController, d as ReviewViewportPreset, V as ViewportSize, e as ReviewItem, N as NumberedReviewItem, f as ReviewItemScope } from './types-DT9Z66mV.cjs';
2
- export { D as DomAnchor, g as DomAnchorCandidate, h as DomAnchorStrategy, i as DomSourceHint, j as RelativeSelection, k as ReviewAssigneeOption, l as ReviewItemKind, m as ReviewItemQuery, n as ReviewMarker, o as ReviewMode, p as ReviewPoint, q as ReviewRulerConfig, r as ReviewSelection, s as ReviewSource, t as ReviewSubmitStatus, u as ReviewViewportScope, v as SupabaseReviewClient, w as WebReviewKitTarget } from './types-DT9Z66mV.cjs';
1
+ import { L as LocalAdapterOptions, W as WebReviewKitAdapter, S as SupabaseReviewAdapterOptions, R as ReviewWorkflowStatus, a as ReviewItemStatus, b as WebReviewKitOptions, c as WebReviewKitController, d as ReviewViewportPreset, V as ViewportSize, e as ReviewItem, N as NumberedReviewItem, f as ReviewItemScope } from './types-BM8E7BFV.cjs';
2
+ export { D as DomAnchor, g as DomAnchorCandidate, h as DomAnchorStrategy, i as DomSourceHint, j as RelativeSelection, k as ReviewAssigneeOption, l as ReviewAttachment, m as ReviewAttachmentKind, n as ReviewAttachmentUploadError, o as ReviewAttachmentUploadErrorReason, p as ReviewAttachmentUploadInput, q as ReviewExternalLink, r as ReviewExternalLinkIcon, s as ReviewItemKind, t as ReviewItemQuery, u as ReviewMarker, v as ReviewMode, w as ReviewPoint, x as ReviewRulerConfig, y as ReviewSelection, z as ReviewSource, A as ReviewSubmitStatus, B as ReviewViewportScope, C as SupabaseReviewClient, E as WebReviewKitTarget } from './types-BM8E7BFV.cjs';
3
3
  import { R as ReviewFigmaImageStore, a as ReviewFigmaImageFormat, b as ReviewFigmaImageTarget } from './image.types-BmzkFSPX.cjs';
4
4
  export { A as AddReviewFigmaImageInput, D as DEFAULT_REVIEW_FIGMA_IMAGE_FORMAT, c as ReorderReviewFigmaImagesInput, d as ReviewFigmaImage, e as ReviewFigmaImageAssetInput, f as ReviewFigmaImageViewport, g as ReviewFigmaNodeTarget, h as ReviewFigmaRouteTarget, U as UpdateReviewFigmaImageInput } from './image.types-BmzkFSPX.cjs';
5
5
  import { R as ReviewFigmaRenderFormat } from './token-Dt-ZH-YO.cjs';
@@ -116,8 +116,15 @@ declare const DEFAULT_REVIEW_VIEWPORTS: ReviewViewportPreset[];
116
116
  declare function findReviewViewportPreset(viewport: ViewportSize, presets?: ReviewViewportPreset[]): ReviewViewportPreset;
117
117
  /** Resolves a viewport size to the review scope used for item grouping. */
118
118
  declare function getReviewViewportScope(viewport: ViewportSize, presets?: ReviewViewportPreset[]): Exclude<ReviewItemScope, 'dom'>;
119
- /** Resolves an item's persisted scope, falling back to its captured viewport. */
120
- declare function getReviewItemScope(item: ReviewItem, presets?: ReviewViewportPreset[]): ReviewItemScope;
119
+ /**
120
+ * Resolves an item's persisted scope, falling back to its captured viewport.
121
+ *
122
+ * 'dom'(구버전 'element') scope 는 의도적으로 뷰포트 scope 로 폴백한다.
123
+ * 마커 표시 조건이 `scope === currentScope`(현재 뷰포트 scope)라서 'dom' 을
124
+ * 그대로 반환하면 레거시 아이템의 마커가 어느 뷰포트에서도 보이지 않게 된다.
125
+ * 현재 코드는 'dom' scope 를 저장하지 않으므로 이 폴백은 레거시 데이터 전용이다.
126
+ */
127
+ declare function getReviewItemScope(item: ReviewItem, presets?: ReviewViewportPreset[]): Exclude<ReviewItemScope, 'dom'>;
121
128
  /** Returns the display label for an item's resolved review scope. */
122
129
  declare function getReviewItemScopeLabel(item: ReviewItem, presets?: ReviewViewportPreset[]): string;
123
130
  /** Adds scope-aware display labels to review items without mutating them. */
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { L as LocalAdapterOptions, W as WebReviewKitAdapter, S as SupabaseReviewAdapterOptions, R as ReviewWorkflowStatus, a as ReviewItemStatus, b as WebReviewKitOptions, c as WebReviewKitController, d as ReviewViewportPreset, V as ViewportSize, e as ReviewItem, N as NumberedReviewItem, f as ReviewItemScope } from './types-DT9Z66mV.js';
2
- export { D as DomAnchor, g as DomAnchorCandidate, h as DomAnchorStrategy, i as DomSourceHint, j as RelativeSelection, k as ReviewAssigneeOption, l as ReviewItemKind, m as ReviewItemQuery, n as ReviewMarker, o as ReviewMode, p as ReviewPoint, q as ReviewRulerConfig, r as ReviewSelection, s as ReviewSource, t as ReviewSubmitStatus, u as ReviewViewportScope, v as SupabaseReviewClient, w as WebReviewKitTarget } from './types-DT9Z66mV.js';
1
+ import { L as LocalAdapterOptions, W as WebReviewKitAdapter, S as SupabaseReviewAdapterOptions, R as ReviewWorkflowStatus, a as ReviewItemStatus, b as WebReviewKitOptions, c as WebReviewKitController, d as ReviewViewportPreset, V as ViewportSize, e as ReviewItem, N as NumberedReviewItem, f as ReviewItemScope } from './types-BM8E7BFV.js';
2
+ export { D as DomAnchor, g as DomAnchorCandidate, h as DomAnchorStrategy, i as DomSourceHint, j as RelativeSelection, k as ReviewAssigneeOption, l as ReviewAttachment, m as ReviewAttachmentKind, n as ReviewAttachmentUploadError, o as ReviewAttachmentUploadErrorReason, p as ReviewAttachmentUploadInput, q as ReviewExternalLink, r as ReviewExternalLinkIcon, s as ReviewItemKind, t as ReviewItemQuery, u as ReviewMarker, v as ReviewMode, w as ReviewPoint, x as ReviewRulerConfig, y as ReviewSelection, z as ReviewSource, A as ReviewSubmitStatus, B as ReviewViewportScope, C as SupabaseReviewClient, E as WebReviewKitTarget } from './types-BM8E7BFV.js';
3
3
  import { R as ReviewFigmaImageStore, a as ReviewFigmaImageFormat, b as ReviewFigmaImageTarget } from './image.types-BmzkFSPX.js';
4
4
  export { A as AddReviewFigmaImageInput, D as DEFAULT_REVIEW_FIGMA_IMAGE_FORMAT, c as ReorderReviewFigmaImagesInput, d as ReviewFigmaImage, e as ReviewFigmaImageAssetInput, f as ReviewFigmaImageViewport, g as ReviewFigmaNodeTarget, h as ReviewFigmaRouteTarget, U as UpdateReviewFigmaImageInput } from './image.types-BmzkFSPX.js';
5
5
  import { R as ReviewFigmaRenderFormat } from './token-nJXPPdYX.js';
@@ -116,8 +116,15 @@ declare const DEFAULT_REVIEW_VIEWPORTS: ReviewViewportPreset[];
116
116
  declare function findReviewViewportPreset(viewport: ViewportSize, presets?: ReviewViewportPreset[]): ReviewViewportPreset;
117
117
  /** Resolves a viewport size to the review scope used for item grouping. */
118
118
  declare function getReviewViewportScope(viewport: ViewportSize, presets?: ReviewViewportPreset[]): Exclude<ReviewItemScope, 'dom'>;
119
- /** Resolves an item's persisted scope, falling back to its captured viewport. */
120
- declare function getReviewItemScope(item: ReviewItem, presets?: ReviewViewportPreset[]): ReviewItemScope;
119
+ /**
120
+ * Resolves an item's persisted scope, falling back to its captured viewport.
121
+ *
122
+ * 'dom'(구버전 'element') scope 는 의도적으로 뷰포트 scope 로 폴백한다.
123
+ * 마커 표시 조건이 `scope === currentScope`(현재 뷰포트 scope)라서 'dom' 을
124
+ * 그대로 반환하면 레거시 아이템의 마커가 어느 뷰포트에서도 보이지 않게 된다.
125
+ * 현재 코드는 'dom' scope 를 저장하지 않으므로 이 폴백은 레거시 데이터 전용이다.
126
+ */
127
+ declare function getReviewItemScope(item: ReviewItem, presets?: ReviewViewportPreset[]): Exclude<ReviewItemScope, 'dom'>;
121
128
  /** Returns the display label for an item's resolved review scope. */
122
129
  declare function getReviewItemScopeLabel(item: ReviewItem, presets?: ReviewViewportPreset[]): string;
123
130
  /** Adds scope-aware display labels to review items without mutating them. */
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  getReviewViewportScope,
11
11
  localAdapter,
12
12
  normalizeReviewItemStatus
13
- } from "./chunk-RPVLRULC.js";
13
+ } from "./chunk-4ZP7B7R6.js";
14
14
  import {
15
15
  DEFAULT_REVIEW_FIGMA_IMAGE_STORE_ENDPOINT,
16
16
  DEFAULT_REVIEW_FIGMA_TOKEN_ENV_KEY,
@@ -198,6 +198,8 @@ function rowToReviewItem(row, options) {
198
198
  const routeKey = row.route_key || item.routeKey || item.normalizedPath || "/";
199
199
  const viewport = item.viewport ?? { width: 390, height: 720 };
200
200
  const now = (/* @__PURE__ */ new Date()).toISOString();
201
+ const kind = normalizeReviewItemKind(item);
202
+ if (!kind) return null;
201
203
  return {
202
204
  ...item,
203
205
  id: row.id,
@@ -206,7 +208,7 @@ function rowToReviewItem(row, options) {
206
208
  routeKey,
207
209
  pageUrl: item.pageUrl || toAbsoluteReviewUrl(routeKey),
208
210
  normalizedPath: item.normalizedPath || routeKey,
209
- kind: item.kind === "area" ? "area" : "note",
211
+ kind,
210
212
  comment: item.comment || "",
211
213
  status,
212
214
  viewport,
@@ -223,6 +225,10 @@ function rowToReviewItem(row, options) {
223
225
  updatedAt: row.updated_at ?? item.updatedAt ?? now
224
226
  };
225
227
  }
228
+ function normalizeReviewItemKind(item) {
229
+ if (item.kind === "area" || item.kind === "dom") return item.kind;
230
+ return null;
231
+ }
226
232
  async function unwrapResponse(request, label) {
227
233
  const { data, error } = await request;
228
234
  if (error) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapters/supabase.ts","../src/figma/remote.image.store.ts"],"sourcesContent":["import { normalizeReviewItemStatus } from '../status';\nimport type {\n ReviewItem,\n ReviewItemStatus,\n ReviewSource,\n SupabaseReviewAdapterOptions,\n WebReviewKitAdapter,\n} from '../types';\n\nconst DEFAULT_SUPABASE_REVIEW_TABLE = 'review_items';\nconst DEFAULT_SUPABASE_REVIEW_SOURCE = 'supabase';\nconst DEFAULT_SUPABASE_CREATE_REVIEW_ITEM_RPC = 'create_review_item';\n\ntype SupabaseReviewRow = {\n id: string;\n project_id: string;\n route_key: string;\n source: string;\n review_number?: number | null;\n status: string;\n item: unknown;\n created_at: string;\n updated_at: string;\n};\n\ntype SupabaseResponse<T> = {\n data: T | null;\n error: { message?: string; code?: string } | null;\n};\n\nexport function supabaseAdapter(\n options: SupabaseReviewAdapterOptions\n): WebReviewKitAdapter {\n const tableName = options.table ?? DEFAULT_SUPABASE_REVIEW_TABLE;\n const source = options.source ?? DEFAULT_SUPABASE_REVIEW_SOURCE;\n\n const fromTable = () => options.client.from(tableName);\n\n return {\n async get(id) {\n const row = await unwrapResponse<SupabaseReviewRow | null>(\n fromTable().select('*').eq('id', id).maybeSingle(),\n 'supabase get review item'\n );\n\n return row ? rowToReviewItem(row, options) : null;\n },\n\n async list(query) {\n let request = fromTable()\n .select('*')\n .eq('project_id', query.projectId)\n .eq('source', query.source ?? source);\n const routeKey = query.routeKey ?? query.normalizedPath;\n\n if (routeKey) {\n request = request.eq('route_key', routeKey);\n }\n if (query.status) {\n request = request.eq(\n 'status',\n normalizeReviewItemStatus(query.status)\n );\n }\n\n const rows = await unwrapResponse<SupabaseReviewRow[]>(\n request.order('created_at', { ascending: false }),\n 'supabase list review items'\n );\n\n return (rows ?? []).flatMap((row) => {\n const item = rowToReviewItem(row, options);\n return item ? [item] : [];\n });\n },\n\n async create(item) {\n const nextItem = normalizeItemForSupabaseCreate(item, source, options);\n\n if (options.unsafeClientReviewNumberFallback) {\n throw new Error(\n 'supabase create review item: unsafeClientReviewNumberFallback is no longer supported. Use create_review_item RPC with database-backed review_number sequence.'\n );\n }\n\n return createItemWithRpc(nextItem, source, options);\n },\n\n async update(id, patch) {\n const current = await this.get(id);\n if (!current) throw new Error(`Review item not found: ${id}`);\n\n const nextStatus = patch.status\n ? normalizeReviewItemStatus(patch.status)\n : current.status;\n const nextItem: ReviewItem = {\n ...current,\n ...patch,\n id,\n status: nextStatus,\n createdAt: current.createdAt,\n updatedAt: new Date().toISOString(),\n };\n const patchRow = itemToRowPatch(nextItem, source, options);\n const updated = await unwrapResponse<SupabaseReviewRow>(\n fromTable().update(patchRow).eq('id', id).select('*').single(),\n 'supabase update review item'\n );\n\n return rowToReviewItem(updated, options) ?? nextItem;\n },\n\n async remove(id) {\n await unwrapResponse<null>(\n fromTable().delete().eq('id', id),\n 'supabase delete review item'\n );\n },\n };\n}\n\nfunction normalizeItemForSupabaseCreate(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n): ReviewItem {\n const now = new Date().toISOString();\n const id = createSupabaseReviewItemId();\n const normalizedStatus = normalizeReviewItemStatus(item.status);\n const routeKey = item.routeKey || item.normalizedPath || '/';\n const viewport = item.viewport ?? { width: 390, height: 720 };\n const nextItem: ReviewItem = {\n ...item,\n id,\n reviewNumber: undefined,\n projectId: options.projectId,\n routeKey,\n normalizedPath: item.normalizedPath || routeKey,\n viewport,\n status: normalizedStatus,\n externalIssueId: id,\n externalIssueUrl: buildSupabaseReviewUrl(\n { routeKey, normalizedPath: item.normalizedPath || routeKey, viewport },\n source,\n options,\n id\n ),\n submittedAt: item.submittedAt ?? now,\n submitStatus: item.submitStatus ?? 'submitted',\n createdAt: now,\n updatedAt: now,\n };\n\n return {\n ...nextItem,\n externalIssueUrl:\n nextItem.externalIssueUrl ??\n buildSupabaseReviewUrl(nextItem, source, options),\n };\n}\n\nasync function createItemWithRpc(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n) {\n const rpcName =\n options.createRpc ?? DEFAULT_SUPABASE_CREATE_REVIEW_ITEM_RPC;\n\n if (!options.client.rpc) {\n throw new Error(\n `supabase create review item: ${rpcName} rpc is required`\n );\n }\n\n const row = await unwrapResponse<SupabaseReviewRow>(\n options.client.rpc(rpcName, {\n p_id: item.id,\n p_project_id: options.projectId,\n p_route_key: item.routeKey || item.normalizedPath || '/',\n p_source: source,\n p_status: normalizeReviewItemStatus(item.status),\n p_item: item,\n }),\n `supabase create review item rpc ${rpcName}`\n );\n\n return rowToReviewItem(row, options) ?? item;\n}\n\nfunction itemToRow(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n): SupabaseReviewRow {\n const now = new Date().toISOString();\n const updatedAt = item.updatedAt || now;\n\n return {\n id: item.id,\n project_id: options.projectId,\n route_key: item.routeKey || item.normalizedPath || '/',\n source,\n review_number: item.reviewNumber ?? null,\n status: normalizeReviewItemStatus(item.status),\n item: {\n ...item,\n projectId: options.projectId,\n status: normalizeReviewItemStatus(item.status),\n updatedAt,\n },\n created_at: item.createdAt || now,\n updated_at: updatedAt,\n };\n}\n\nfunction itemToRowPatch(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n) {\n const row = itemToRow(item, source, options);\n return {\n route_key: row.route_key,\n review_number: row.review_number,\n status: row.status,\n item: row.item,\n updated_at: row.updated_at,\n };\n}\n\nfunction rowToReviewItem(\n row: SupabaseReviewRow,\n options: SupabaseReviewAdapterOptions\n): ReviewItem | null {\n if (!row.item || typeof row.item !== 'object') return null;\n\n const item = row.item as Partial<ReviewItem>;\n const status = normalizeReviewItemStatus(\n (row.status || item.status || 'todo') as ReviewItemStatus\n );\n const routeKey = row.route_key || item.routeKey || item.normalizedPath || '/';\n const viewport = item.viewport ?? { width: 390, height: 720 };\n const now = new Date().toISOString();\n\n return {\n ...(item as ReviewItem),\n id: row.id,\n reviewNumber: row.review_number ?? item.reviewNumber,\n projectId: row.project_id || item.projectId || options.projectId,\n routeKey,\n pageUrl: item.pageUrl || toAbsoluteReviewUrl(routeKey),\n normalizedPath: item.normalizedPath || routeKey,\n kind: item.kind === 'area' ? 'area' : 'note',\n comment: item.comment || '',\n status,\n viewport,\n externalIssueId: item.externalIssueId ?? row.id,\n externalIssueUrl:\n item.externalIssueUrl ??\n buildSupabaseReviewUrl(\n { routeKey, normalizedPath: routeKey, viewport },\n row.source,\n options,\n row.id\n ),\n submittedAt: item.submittedAt ?? row.created_at,\n submitStatus: item.submitStatus ?? 'submitted',\n createdAt: item.createdAt ?? row.created_at ?? now,\n updatedAt: row.updated_at ?? item.updatedAt ?? now,\n };\n}\n\nasync function unwrapResponse<T>(\n request: Promise<SupabaseResponse<T>> | SupabaseResponse<T>,\n label: string\n) {\n const { data, error } = await request;\n if (error) {\n throw new Error(`${label}: ${error.message ?? error.code ?? 'failed'}`);\n }\n return data as T;\n}\n\nfunction buildSupabaseReviewUrl(\n item: Pick<ReviewItem, 'routeKey' | 'normalizedPath' | 'viewport'>,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions,\n itemId?: string\n) {\n if (typeof window === 'undefined') return undefined;\n\n const url = new URL(\n normalizeReviewUrlPath(options.reviewPathPrefix),\n window.location.origin\n );\n url.searchParams.set('source', source);\n url.searchParams.set('target', item.routeKey || item.normalizedPath || '/');\n url.searchParams.set('w', String(Math.round(item.viewport.width)));\n url.searchParams.set('h', String(Math.round(item.viewport.height)));\n if (itemId) url.searchParams.set('item', itemId);\n return url.toString();\n}\n\nfunction normalizeReviewUrlPath(value = '/review') {\n const raw = value.trim() || '/review';\n const path = raw.startsWith('/') ? raw : `/${raw}`;\n return path.endsWith('/') ? path : `${path}/`;\n}\n\nfunction toAbsoluteReviewUrl(path: string) {\n if (typeof window === 'undefined') return path;\n return new URL(path, window.location.origin).toString();\n}\n\nfunction createSupabaseReviewItemId() {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n return `review-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n","import type {\n AddReviewFigmaImageInput,\n ReviewFigmaImage,\n ReviewFigmaImageAssetInput,\n ReviewFigmaImageFormat,\n ReviewFigmaImageStore,\n ReviewFigmaImageTarget,\n UpdateReviewFigmaImageInput,\n} from './image.types';\nimport {\n createReviewFigmaClientRenderedAsset,\n getReviewFigmaImageTargetKey,\n type ReviewFigmaImageClientRenderOptions,\n} from './image.store';\nimport { parseReviewFigmaNodeRef } from './parse';\n\nexport const DEFAULT_REVIEW_FIGMA_REMOTE_IMAGES_TABLE = 'review_figma_images';\nconst DEFAULT_REVIEW_FIGMA_REMOTE_UPLOAD_TIMEOUT_MS = 30000;\nconst FIGMA_TOKEN_STORAGE_KEY = 'figma-token';\n\ntype ReviewFigmaRemoteTokenProvider =\n | string\n | null\n | undefined\n | (() => string | null | undefined);\n\nexport type ReviewFigmaRemoteImageRow = {\n id: string;\n project_id: string;\n target_key: string;\n target: ReviewFigmaImageTarget;\n target_type: 'route' | 'figma-node';\n page_url: string | null;\n viewport_label: string | null;\n viewport_width: number | null;\n viewport_height: number | null;\n viewport_scope: 'mobile' | 'tablet' | 'desktop' | 'wide' | null;\n slot: string | null;\n figma_url: string;\n file_key: string;\n node_id: string;\n image_url: string;\n image_format: ReviewFigmaImageFormat;\n mime_type: string;\n storage_key: string;\n label: string | null;\n sort_order: number;\n width: number | null;\n height: number | null;\n byte_size: number | null;\n created_at: string;\n updated_at: string;\n};\n\ntype ReviewFigmaRemoteDbResult<T = unknown> = {\n data: T | null;\n error: unknown;\n};\n\ntype ReviewFigmaRemoteDbQuery<T = unknown> = PromiseLike<\n ReviewFigmaRemoteDbResult<T>\n> & {\n delete(): ReviewFigmaRemoteDbQuery<T>;\n eq(column: string, value: unknown): ReviewFigmaRemoteDbQuery<T>;\n insert(value: unknown): ReviewFigmaRemoteDbQuery<T>;\n order(\n column: string,\n options?: { ascending?: boolean }\n ): ReviewFigmaRemoteDbQuery<T>;\n select(columns?: string): ReviewFigmaRemoteDbQuery<T>;\n single(): PromiseLike<ReviewFigmaRemoteDbResult<T>>;\n update(value: unknown): ReviewFigmaRemoteDbQuery<T>;\n};\n\nexport type ReviewFigmaRemoteDbClient = {\n from(table: string): ReviewFigmaRemoteDbQuery;\n};\n\nexport type ReviewFigmaRemoteAssetUploadResponse = {\n storageKey?: unknown;\n r2Key?: unknown;\n imageUrl?: unknown;\n publicUrl?: unknown;\n error?: unknown;\n};\n\nexport type RemoteReviewFigmaImageStoreOptions = {\n client: ReviewFigmaRemoteDbClient;\n uploadEndpoint: string;\n table?: string;\n fetch?: typeof fetch;\n token?: ReviewFigmaRemoteTokenProvider;\n clientRender?: boolean | ReviewFigmaImageClientRenderOptions;\n uploadTimeoutMs?: number;\n};\n\nexport function createRemoteReviewFigmaImageStore({\n client,\n uploadEndpoint,\n table = DEFAULT_REVIEW_FIGMA_REMOTE_IMAGES_TABLE,\n fetch: fetchOption,\n token,\n clientRender = true,\n uploadTimeoutMs = DEFAULT_REVIEW_FIGMA_REMOTE_UPLOAD_TIMEOUT_MS,\n}: RemoteReviewFigmaImageStoreOptions): ReviewFigmaImageStore {\n const listImages = async (target: ReviewFigmaImageTarget) => {\n const targetKey = getReviewFigmaImageTargetKey(target);\n const { data, error } = await client\n .from(table)\n .select('*')\n .eq('project_id', target.projectId)\n .eq('target_key', targetKey)\n .order('sort_order', { ascending: true })\n .order('created_at', { ascending: true });\n\n if (error) throwRemoteStoreError(error, 'list Figma images');\n return ((data ?? []) as ReviewFigmaRemoteImageRow[]).map(rowToFigmaImage);\n };\n\n return {\n listImages,\n async addImage(input) {\n const ref = parseReviewFigmaNodeRef(input.figmaUrl);\n if (!ref) {\n throw new Error('A Figma node link or fileKey->nodeId value is required.');\n }\n\n const id = createFigmaImageId();\n const asset = await resolveFigmaImageAsset({\n input,\n token,\n clientRender,\n fetch: fetchOption,\n });\n const uploaded = await uploadFigmaAsset({\n asset,\n endpoint: uploadEndpoint,\n fetch: fetchOption,\n imageId: id,\n projectId: input.target.projectId,\n timeoutMs: uploadTimeoutMs,\n });\n const order =\n typeof input.order === 'number' && Number.isFinite(input.order)\n ? input.order\n : await getNextImageOrder(listImages, input.target);\n const now = new Date().toISOString();\n const row = createImageRow({\n asset,\n fileKey: ref.fileKey,\n id,\n imageUrl: uploaded.imageUrl,\n input,\n nodeId: ref.nodeId,\n now,\n order,\n storageKey: uploaded.storageKey,\n });\n const { data, error } = await client\n .from(table)\n .insert(row)\n .select('*')\n .single();\n\n if (error) throwRemoteStoreError(error, 'insert Figma image');\n return rowToFigmaImage(data as ReviewFigmaRemoteImageRow);\n },\n async updateImage(id, patch) {\n const { data, error } = await client\n .from(table)\n .update(createUpdatePatch(patch))\n .eq('id', id)\n .select('*')\n .single();\n\n if (error) throwRemoteStoreError(error, 'update Figma image');\n return rowToFigmaImage(data as ReviewFigmaRemoteImageRow);\n },\n async reorderImages(input) {\n const current = await listImages(input.target);\n const currentIds = new Set(current.map((image) => image.id));\n const nextIds = [\n ...input.imageIds.filter((id) => currentIds.has(id)),\n ...current\n .map((image) => image.id)\n .filter((id) => !input.imageIds.includes(id)),\n ];\n const targetKey = getReviewFigmaImageTargetKey(input.target);\n const updatedAt = new Date().toISOString();\n\n const results = await Promise.all(\n nextIds.map((id, index) =>\n client\n .from(table)\n .update({ sort_order: index, updated_at: updatedAt })\n .eq('id', id)\n .eq('project_id', input.target.projectId)\n .eq('target_key', targetKey)\n )\n );\n const failed = results.find((result) => result.error);\n if (failed?.error) throwRemoteStoreError(failed.error, 'reorder Figma images');\n\n return listImages(input.target);\n },\n async deleteImage(id) {\n const { error } = await client.from(table).delete().eq('id', id);\n if (error) throwRemoteStoreError(error, 'delete Figma image');\n },\n };\n}\n\nasync function resolveFigmaImageAsset({\n input,\n token,\n clientRender,\n fetch,\n}: {\n input: AddReviewFigmaImageInput;\n token: ReviewFigmaRemoteTokenProvider;\n clientRender: boolean | ReviewFigmaImageClientRenderOptions;\n fetch: typeof globalThis.fetch | undefined;\n}) {\n if (input.asset) return input.asset;\n if (!clientRender) {\n throw new Error('Figma image asset is required when clientRender is disabled.');\n }\n\n const renderOptions = clientRender === true ? {} : clientRender;\n const figmaToken = readRemoteFigmaToken(renderOptions.token ?? token);\n if (!figmaToken) throw new Error('Figma token is required.');\n\n return createReviewFigmaClientRenderedAsset({\n ...renderOptions,\n fetch,\n figmaUrl: input.figmaUrl,\n token: figmaToken,\n });\n}\n\nasync function uploadFigmaAsset({\n asset,\n endpoint,\n fetch: fetchOption,\n imageId,\n projectId,\n timeoutMs,\n}: {\n asset: ReviewFigmaImageAssetInput;\n endpoint: string;\n fetch: typeof globalThis.fetch | undefined;\n imageId: string;\n projectId: string;\n timeoutMs: number;\n}) {\n const requestFetch = fetchOption ?? globalThis.fetch;\n if (!requestFetch) throw new Error('Figma asset upload requires fetch.');\n\n const { blob, mimeType } = decodeAssetDataUrl(asset);\n const response = await withTimeout(\n requestFetch(\n createAssetUploadUrl(endpoint, {\n imageFormat: asset.imageFormat,\n imageId,\n projectId,\n }),\n {\n method: 'POST',\n headers: {\n 'Content-Type': mimeType,\n },\n body: blob,\n }\n ),\n timeoutMs,\n 'Figma asset upload timed out.'\n );\n const data = (await response.json().catch(() => null)) as\n | ReviewFigmaRemoteAssetUploadResponse\n | null;\n\n if (!response.ok) {\n throw new Error(\n readString(data?.error) || `Figma asset upload failed with ${response.status}`\n );\n }\n\n const storageKey = readString(data?.storageKey) ?? readString(data?.r2Key);\n const imageUrl = readString(data?.imageUrl) ?? readString(data?.publicUrl);\n if (!storageKey || !imageUrl) {\n throw new Error('Figma asset upload response is missing image URL.');\n }\n\n return { storageKey, imageUrl };\n}\n\nfunction createAssetUploadUrl(\n endpoint: string,\n params: {\n imageFormat: ReviewFigmaImageFormat;\n imageId: string;\n projectId: string;\n }\n) {\n const base =\n typeof window !== 'undefined' ? window.location.origin : 'http://localhost';\n const url = new URL(endpoint, base);\n url.searchParams.set('projectId', params.projectId);\n url.searchParams.set('imageId', params.imageId);\n url.searchParams.set('imageFormat', params.imageFormat);\n return url.toString();\n}\n\nfunction createImageRow({\n asset,\n fileKey,\n id,\n imageUrl,\n input,\n nodeId,\n now,\n order,\n storageKey,\n}: {\n asset: ReviewFigmaImageAssetInput;\n fileKey: string;\n id: string;\n imageUrl: string;\n input: AddReviewFigmaImageInput;\n nodeId: string;\n now: string;\n order: number;\n storageKey: string;\n}): ReviewFigmaRemoteImageRow {\n const target = input.target;\n const targetKey = getReviewFigmaImageTargetKey(target);\n\n return {\n id,\n project_id: target.projectId,\n target_key: targetKey,\n target,\n target_type: target.type,\n page_url: target.type === 'route' ? target.pageUrl : null,\n viewport_label: target.type === 'route' ? target.viewport?.label ?? null : null,\n viewport_width: target.type === 'route' ? target.viewport?.width ?? null : null,\n viewport_height: target.type === 'route' ? target.viewport?.height ?? null : null,\n viewport_scope: target.type === 'route' ? target.viewport?.scope ?? null : null,\n slot: target.type === 'route' ? target.slot ?? null : null,\n figma_url: input.figmaUrl,\n file_key: fileKey,\n node_id: nodeId,\n image_url: imageUrl,\n image_format: asset.imageFormat,\n mime_type: asset.mimeType,\n storage_key: storageKey,\n label: normalizeOptionalText(input.label) ?? null,\n sort_order: order,\n width: asset.width ?? null,\n height: asset.height ?? null,\n byte_size: asset.byteSize ?? null,\n created_at: now,\n updated_at: now,\n };\n}\n\nfunction createUpdatePatch(patch: UpdateReviewFigmaImageInput) {\n return {\n ...(patch.label !== undefined\n ? { label: normalizeOptionalText(patch.label) ?? null }\n : {}),\n ...(typeof patch.order === 'number' && Number.isFinite(patch.order)\n ? { sort_order: patch.order }\n : {}),\n updated_at: new Date().toISOString(),\n };\n}\n\nasync function getNextImageOrder(\n listImages: (target: ReviewFigmaImageTarget) => Promise<ReviewFigmaImage[]>,\n target: ReviewFigmaImageTarget\n) {\n const images = await listImages(target);\n return images.length\n ? Math.max(...images.map((image) => image.order)) + 1\n : 0;\n}\n\nfunction rowToFigmaImage(row: ReviewFigmaRemoteImageRow): ReviewFigmaImage {\n return {\n id: row.id,\n projectId: row.project_id,\n target: row.target,\n figmaUrl: row.figma_url,\n fileKey: row.file_key,\n nodeId: row.node_id,\n imageUrl: row.image_url,\n imageFormat: row.image_format,\n mimeType: row.mime_type,\n label: row.label ?? undefined,\n order: row.sort_order,\n storageKey: row.storage_key,\n width: row.width ?? undefined,\n height: row.height ?? undefined,\n byteSize: row.byte_size ?? undefined,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nfunction decodeAssetDataUrl(asset: ReviewFigmaImageAssetInput) {\n const match = asset.dataUrl.match(/^data:([^;,]+);base64,(.*)$/);\n if (!match) throw new Error('Valid Figma image asset data URL is required.');\n\n const mimeType = match[1]?.trim();\n if (!mimeType || mimeType !== asset.mimeType) {\n throw new Error('Figma image asset MIME type mismatch.');\n }\n\n const binary = globalThis.atob(match[2] ?? '');\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n\n return {\n blob: new Blob([bytes], { type: mimeType }),\n mimeType,\n };\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message: string\n) {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<T>((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error(message)), timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutId) clearTimeout(timeoutId);\n }\n}\n\nfunction readRemoteFigmaToken(provider: ReviewFigmaRemoteTokenProvider) {\n const token = typeof provider === 'function' ? provider() : provider;\n if (typeof token === 'string' && token.trim()) return token.trim();\n return readStoredFigmaToken();\n}\n\nfunction readStoredFigmaToken() {\n if (typeof window === 'undefined') return '';\n\n try {\n return window.localStorage.getItem(FIGMA_TOKEN_STORAGE_KEY)?.trim() || '';\n } catch {\n return '';\n }\n}\n\nfunction createFigmaImageId() {\n const id =\n globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2);\n return `figma_${id.replace(/[^A-Za-z0-9_-]+/g, '-')}`;\n}\n\nfunction normalizeOptionalText(value: string | null | undefined) {\n if (typeof value !== 'string') return undefined;\n return value.trim() || undefined;\n}\n\nfunction readString(value: unknown) {\n return typeof value === 'string' && value.trim() ? value.trim() : null;\n}\n\nfunction throwRemoteStoreError(error: unknown, action: string): never {\n const source = error as {\n code?: unknown;\n details?: unknown;\n hint?: unknown;\n message?: unknown;\n };\n const message = readString(source.message) ?? `Remote Figma image ${action} failed.`;\n const code = readString(source.code);\n const details = readString(source.details);\n const hint = readString(source.hint);\n const suffix = [code, details, hint].filter(Boolean).join(' / ');\n\n throw new Error(suffix ? `${message} (${suffix})` : message);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/adapters/supabase.ts","../src/figma/remote.image.store.ts"],"sourcesContent":["import { normalizeReviewItemStatus } from '../status';\nimport type {\n ReviewItem,\n ReviewItemKind,\n ReviewItemStatus,\n ReviewSource,\n SupabaseReviewAdapterOptions,\n WebReviewKitAdapter,\n} from '../types';\n\nconst DEFAULT_SUPABASE_REVIEW_TABLE = 'review_items';\nconst DEFAULT_SUPABASE_REVIEW_SOURCE = 'supabase';\nconst DEFAULT_SUPABASE_CREATE_REVIEW_ITEM_RPC = 'create_review_item';\n\ntype SupabaseReviewRow = {\n id: string;\n project_id: string;\n route_key: string;\n source: string;\n review_number?: number | null;\n status: string;\n item: unknown;\n created_at: string;\n updated_at: string;\n};\n\ntype SupabaseResponse<T> = {\n data: T | null;\n error: { message?: string; code?: string } | null;\n};\n\nexport function supabaseAdapter(\n options: SupabaseReviewAdapterOptions\n): WebReviewKitAdapter {\n const tableName = options.table ?? DEFAULT_SUPABASE_REVIEW_TABLE;\n const source = options.source ?? DEFAULT_SUPABASE_REVIEW_SOURCE;\n\n const fromTable = () => options.client.from(tableName);\n\n return {\n async get(id) {\n const row = await unwrapResponse<SupabaseReviewRow | null>(\n fromTable().select('*').eq('id', id).maybeSingle(),\n 'supabase get review item'\n );\n\n return row ? rowToReviewItem(row, options) : null;\n },\n\n async list(query) {\n let request = fromTable()\n .select('*')\n .eq('project_id', query.projectId)\n .eq('source', query.source ?? source);\n const routeKey = query.routeKey ?? query.normalizedPath;\n\n if (routeKey) {\n request = request.eq('route_key', routeKey);\n }\n if (query.status) {\n request = request.eq(\n 'status',\n normalizeReviewItemStatus(query.status)\n );\n }\n\n const rows = await unwrapResponse<SupabaseReviewRow[]>(\n request.order('created_at', { ascending: false }),\n 'supabase list review items'\n );\n\n return (rows ?? []).flatMap((row) => {\n const item = rowToReviewItem(row, options);\n return item ? [item] : [];\n });\n },\n\n async create(item) {\n const nextItem = normalizeItemForSupabaseCreate(item, source, options);\n\n if (options.unsafeClientReviewNumberFallback) {\n throw new Error(\n 'supabase create review item: unsafeClientReviewNumberFallback is no longer supported. Use create_review_item RPC with database-backed review_number sequence.'\n );\n }\n\n return createItemWithRpc(nextItem, source, options);\n },\n\n async update(id, patch) {\n const current = await this.get(id);\n if (!current) throw new Error(`Review item not found: ${id}`);\n\n const nextStatus = patch.status\n ? normalizeReviewItemStatus(patch.status)\n : current.status;\n const nextItem: ReviewItem = {\n ...current,\n ...patch,\n id,\n status: nextStatus,\n createdAt: current.createdAt,\n updatedAt: new Date().toISOString(),\n };\n const patchRow = itemToRowPatch(nextItem, source, options);\n const updated = await unwrapResponse<SupabaseReviewRow>(\n fromTable().update(patchRow).eq('id', id).select('*').single(),\n 'supabase update review item'\n );\n\n return rowToReviewItem(updated, options) ?? nextItem;\n },\n\n async remove(id) {\n await unwrapResponse<null>(\n fromTable().delete().eq('id', id),\n 'supabase delete review item'\n );\n },\n };\n}\n\nfunction normalizeItemForSupabaseCreate(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n): ReviewItem {\n const now = new Date().toISOString();\n const id = createSupabaseReviewItemId();\n const normalizedStatus = normalizeReviewItemStatus(item.status);\n const routeKey = item.routeKey || item.normalizedPath || '/';\n const viewport = item.viewport ?? { width: 390, height: 720 };\n const nextItem: ReviewItem = {\n ...item,\n id,\n reviewNumber: undefined,\n projectId: options.projectId,\n routeKey,\n normalizedPath: item.normalizedPath || routeKey,\n viewport,\n status: normalizedStatus,\n externalIssueId: id,\n externalIssueUrl: buildSupabaseReviewUrl(\n { routeKey, normalizedPath: item.normalizedPath || routeKey, viewport },\n source,\n options,\n id\n ),\n submittedAt: item.submittedAt ?? now,\n submitStatus: item.submitStatus ?? 'submitted',\n createdAt: now,\n updatedAt: now,\n };\n\n return {\n ...nextItem,\n externalIssueUrl:\n nextItem.externalIssueUrl ??\n buildSupabaseReviewUrl(nextItem, source, options),\n };\n}\n\nasync function createItemWithRpc(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n) {\n const rpcName =\n options.createRpc ?? DEFAULT_SUPABASE_CREATE_REVIEW_ITEM_RPC;\n\n if (!options.client.rpc) {\n throw new Error(\n `supabase create review item: ${rpcName} rpc is required`\n );\n }\n\n const row = await unwrapResponse<SupabaseReviewRow>(\n options.client.rpc(rpcName, {\n p_id: item.id,\n p_project_id: options.projectId,\n p_route_key: item.routeKey || item.normalizedPath || '/',\n p_source: source,\n p_status: normalizeReviewItemStatus(item.status),\n p_item: item,\n }),\n `supabase create review item rpc ${rpcName}`\n );\n\n return rowToReviewItem(row, options) ?? item;\n}\n\nfunction itemToRow(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n): SupabaseReviewRow {\n const now = new Date().toISOString();\n const updatedAt = item.updatedAt || now;\n\n return {\n id: item.id,\n project_id: options.projectId,\n route_key: item.routeKey || item.normalizedPath || '/',\n source,\n review_number: item.reviewNumber ?? null,\n status: normalizeReviewItemStatus(item.status),\n item: {\n ...item,\n projectId: options.projectId,\n status: normalizeReviewItemStatus(item.status),\n updatedAt,\n },\n created_at: item.createdAt || now,\n updated_at: updatedAt,\n };\n}\n\nfunction itemToRowPatch(\n item: ReviewItem,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions\n) {\n const row = itemToRow(item, source, options);\n return {\n route_key: row.route_key,\n review_number: row.review_number,\n status: row.status,\n item: row.item,\n updated_at: row.updated_at,\n };\n}\n\nfunction rowToReviewItem(\n row: SupabaseReviewRow,\n options: SupabaseReviewAdapterOptions\n): ReviewItem | null {\n if (!row.item || typeof row.item !== 'object') return null;\n\n const item = row.item as Partial<Omit<ReviewItem, 'kind'>> & {\n kind?: string;\n };\n const status = normalizeReviewItemStatus(\n (row.status || item.status || 'todo') as ReviewItemStatus\n );\n const routeKey = row.route_key || item.routeKey || item.normalizedPath || '/';\n const viewport = item.viewport ?? { width: 390, height: 720 };\n const now = new Date().toISOString();\n const kind = normalizeReviewItemKind(item);\n if (!kind) return null;\n\n return {\n ...(item as ReviewItem),\n id: row.id,\n reviewNumber: row.review_number ?? item.reviewNumber,\n projectId: row.project_id || item.projectId || options.projectId,\n routeKey,\n pageUrl: item.pageUrl || toAbsoluteReviewUrl(routeKey),\n normalizedPath: item.normalizedPath || routeKey,\n kind,\n comment: item.comment || '',\n status,\n viewport,\n externalIssueId: item.externalIssueId ?? row.id,\n externalIssueUrl:\n item.externalIssueUrl ??\n buildSupabaseReviewUrl(\n { routeKey, normalizedPath: routeKey, viewport },\n row.source,\n options,\n row.id\n ),\n submittedAt: item.submittedAt ?? row.created_at,\n submitStatus: item.submitStatus ?? 'submitted',\n createdAt: item.createdAt ?? row.created_at ?? now,\n updatedAt: row.updated_at ?? item.updatedAt ?? now,\n };\n}\n\nfunction normalizeReviewItemKind(\n item: Partial<Omit<ReviewItem, 'kind'>> & { kind?: string }\n): ReviewItemKind | null {\n if (item.kind === 'area' || item.kind === 'dom') return item.kind;\n return null;\n}\n\nasync function unwrapResponse<T>(\n request: Promise<SupabaseResponse<T>> | SupabaseResponse<T>,\n label: string\n) {\n const { data, error } = await request;\n if (error) {\n throw new Error(`${label}: ${error.message ?? error.code ?? 'failed'}`);\n }\n return data as T;\n}\n\nfunction buildSupabaseReviewUrl(\n item: Pick<ReviewItem, 'routeKey' | 'normalizedPath' | 'viewport'>,\n source: ReviewSource,\n options: SupabaseReviewAdapterOptions,\n itemId?: string\n) {\n if (typeof window === 'undefined') return undefined;\n\n const url = new URL(\n normalizeReviewUrlPath(options.reviewPathPrefix),\n window.location.origin\n );\n url.searchParams.set('source', source);\n url.searchParams.set('target', item.routeKey || item.normalizedPath || '/');\n url.searchParams.set('w', String(Math.round(item.viewport.width)));\n url.searchParams.set('h', String(Math.round(item.viewport.height)));\n if (itemId) url.searchParams.set('item', itemId);\n return url.toString();\n}\n\nfunction normalizeReviewUrlPath(value = '/review') {\n const raw = value.trim() || '/review';\n const path = raw.startsWith('/') ? raw : `/${raw}`;\n return path.endsWith('/') ? path : `${path}/`;\n}\n\nfunction toAbsoluteReviewUrl(path: string) {\n if (typeof window === 'undefined') return path;\n return new URL(path, window.location.origin).toString();\n}\n\nfunction createSupabaseReviewItemId() {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n return `review-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n","import type {\n AddReviewFigmaImageInput,\n ReviewFigmaImage,\n ReviewFigmaImageAssetInput,\n ReviewFigmaImageFormat,\n ReviewFigmaImageStore,\n ReviewFigmaImageTarget,\n UpdateReviewFigmaImageInput,\n} from './image.types';\nimport {\n createReviewFigmaClientRenderedAsset,\n getReviewFigmaImageTargetKey,\n type ReviewFigmaImageClientRenderOptions,\n} from './image.store';\nimport { parseReviewFigmaNodeRef } from './parse';\n\nexport const DEFAULT_REVIEW_FIGMA_REMOTE_IMAGES_TABLE = 'review_figma_images';\nconst DEFAULT_REVIEW_FIGMA_REMOTE_UPLOAD_TIMEOUT_MS = 30000;\nconst FIGMA_TOKEN_STORAGE_KEY = 'figma-token';\n\ntype ReviewFigmaRemoteTokenProvider =\n | string\n | null\n | undefined\n | (() => string | null | undefined);\n\nexport type ReviewFigmaRemoteImageRow = {\n id: string;\n project_id: string;\n target_key: string;\n target: ReviewFigmaImageTarget;\n target_type: 'route' | 'figma-node';\n page_url: string | null;\n viewport_label: string | null;\n viewport_width: number | null;\n viewport_height: number | null;\n viewport_scope: 'mobile' | 'tablet' | 'desktop' | 'wide' | null;\n slot: string | null;\n figma_url: string;\n file_key: string;\n node_id: string;\n image_url: string;\n image_format: ReviewFigmaImageFormat;\n mime_type: string;\n storage_key: string;\n label: string | null;\n sort_order: number;\n width: number | null;\n height: number | null;\n byte_size: number | null;\n created_at: string;\n updated_at: string;\n};\n\ntype ReviewFigmaRemoteDbResult<T = unknown> = {\n data: T | null;\n error: unknown;\n};\n\ntype ReviewFigmaRemoteDbQuery<T = unknown> = PromiseLike<\n ReviewFigmaRemoteDbResult<T>\n> & {\n delete(): ReviewFigmaRemoteDbQuery<T>;\n eq(column: string, value: unknown): ReviewFigmaRemoteDbQuery<T>;\n insert(value: unknown): ReviewFigmaRemoteDbQuery<T>;\n order(\n column: string,\n options?: { ascending?: boolean }\n ): ReviewFigmaRemoteDbQuery<T>;\n select(columns?: string): ReviewFigmaRemoteDbQuery<T>;\n single(): PromiseLike<ReviewFigmaRemoteDbResult<T>>;\n update(value: unknown): ReviewFigmaRemoteDbQuery<T>;\n};\n\nexport type ReviewFigmaRemoteDbClient = {\n from(table: string): ReviewFigmaRemoteDbQuery;\n};\n\nexport type ReviewFigmaRemoteAssetUploadResponse = {\n storageKey?: unknown;\n r2Key?: unknown;\n imageUrl?: unknown;\n publicUrl?: unknown;\n error?: unknown;\n};\n\nexport type RemoteReviewFigmaImageStoreOptions = {\n client: ReviewFigmaRemoteDbClient;\n uploadEndpoint: string;\n table?: string;\n fetch?: typeof fetch;\n token?: ReviewFigmaRemoteTokenProvider;\n clientRender?: boolean | ReviewFigmaImageClientRenderOptions;\n uploadTimeoutMs?: number;\n};\n\nexport function createRemoteReviewFigmaImageStore({\n client,\n uploadEndpoint,\n table = DEFAULT_REVIEW_FIGMA_REMOTE_IMAGES_TABLE,\n fetch: fetchOption,\n token,\n clientRender = true,\n uploadTimeoutMs = DEFAULT_REVIEW_FIGMA_REMOTE_UPLOAD_TIMEOUT_MS,\n}: RemoteReviewFigmaImageStoreOptions): ReviewFigmaImageStore {\n const listImages = async (target: ReviewFigmaImageTarget) => {\n const targetKey = getReviewFigmaImageTargetKey(target);\n const { data, error } = await client\n .from(table)\n .select('*')\n .eq('project_id', target.projectId)\n .eq('target_key', targetKey)\n .order('sort_order', { ascending: true })\n .order('created_at', { ascending: true });\n\n if (error) throwRemoteStoreError(error, 'list Figma images');\n return ((data ?? []) as ReviewFigmaRemoteImageRow[]).map(rowToFigmaImage);\n };\n\n return {\n listImages,\n async addImage(input) {\n const ref = parseReviewFigmaNodeRef(input.figmaUrl);\n if (!ref) {\n throw new Error('A Figma node link or fileKey->nodeId value is required.');\n }\n\n const id = createFigmaImageId();\n const asset = await resolveFigmaImageAsset({\n input,\n token,\n clientRender,\n fetch: fetchOption,\n });\n const uploaded = await uploadFigmaAsset({\n asset,\n endpoint: uploadEndpoint,\n fetch: fetchOption,\n imageId: id,\n projectId: input.target.projectId,\n timeoutMs: uploadTimeoutMs,\n });\n const order =\n typeof input.order === 'number' && Number.isFinite(input.order)\n ? input.order\n : await getNextImageOrder(listImages, input.target);\n const now = new Date().toISOString();\n const row = createImageRow({\n asset,\n fileKey: ref.fileKey,\n id,\n imageUrl: uploaded.imageUrl,\n input,\n nodeId: ref.nodeId,\n now,\n order,\n storageKey: uploaded.storageKey,\n });\n const { data, error } = await client\n .from(table)\n .insert(row)\n .select('*')\n .single();\n\n if (error) throwRemoteStoreError(error, 'insert Figma image');\n return rowToFigmaImage(data as ReviewFigmaRemoteImageRow);\n },\n async updateImage(id, patch) {\n const { data, error } = await client\n .from(table)\n .update(createUpdatePatch(patch))\n .eq('id', id)\n .select('*')\n .single();\n\n if (error) throwRemoteStoreError(error, 'update Figma image');\n return rowToFigmaImage(data as ReviewFigmaRemoteImageRow);\n },\n async reorderImages(input) {\n const current = await listImages(input.target);\n const currentIds = new Set(current.map((image) => image.id));\n const nextIds = [\n ...input.imageIds.filter((id) => currentIds.has(id)),\n ...current\n .map((image) => image.id)\n .filter((id) => !input.imageIds.includes(id)),\n ];\n const targetKey = getReviewFigmaImageTargetKey(input.target);\n const updatedAt = new Date().toISOString();\n\n const results = await Promise.all(\n nextIds.map((id, index) =>\n client\n .from(table)\n .update({ sort_order: index, updated_at: updatedAt })\n .eq('id', id)\n .eq('project_id', input.target.projectId)\n .eq('target_key', targetKey)\n )\n );\n const failed = results.find((result) => result.error);\n if (failed?.error) throwRemoteStoreError(failed.error, 'reorder Figma images');\n\n return listImages(input.target);\n },\n async deleteImage(id) {\n const { error } = await client.from(table).delete().eq('id', id);\n if (error) throwRemoteStoreError(error, 'delete Figma image');\n },\n };\n}\n\nasync function resolveFigmaImageAsset({\n input,\n token,\n clientRender,\n fetch,\n}: {\n input: AddReviewFigmaImageInput;\n token: ReviewFigmaRemoteTokenProvider;\n clientRender: boolean | ReviewFigmaImageClientRenderOptions;\n fetch: typeof globalThis.fetch | undefined;\n}) {\n if (input.asset) return input.asset;\n if (!clientRender) {\n throw new Error('Figma image asset is required when clientRender is disabled.');\n }\n\n const renderOptions = clientRender === true ? {} : clientRender;\n const figmaToken = readRemoteFigmaToken(renderOptions.token ?? token);\n if (!figmaToken) throw new Error('Figma token is required.');\n\n return createReviewFigmaClientRenderedAsset({\n ...renderOptions,\n fetch,\n figmaUrl: input.figmaUrl,\n token: figmaToken,\n });\n}\n\nasync function uploadFigmaAsset({\n asset,\n endpoint,\n fetch: fetchOption,\n imageId,\n projectId,\n timeoutMs,\n}: {\n asset: ReviewFigmaImageAssetInput;\n endpoint: string;\n fetch: typeof globalThis.fetch | undefined;\n imageId: string;\n projectId: string;\n timeoutMs: number;\n}) {\n const requestFetch = fetchOption ?? globalThis.fetch;\n if (!requestFetch) throw new Error('Figma asset upload requires fetch.');\n\n const { blob, mimeType } = decodeAssetDataUrl(asset);\n const response = await withTimeout(\n requestFetch(\n createAssetUploadUrl(endpoint, {\n imageFormat: asset.imageFormat,\n imageId,\n projectId,\n }),\n {\n method: 'POST',\n headers: {\n 'Content-Type': mimeType,\n },\n body: blob,\n }\n ),\n timeoutMs,\n 'Figma asset upload timed out.'\n );\n const data = (await response.json().catch(() => null)) as\n | ReviewFigmaRemoteAssetUploadResponse\n | null;\n\n if (!response.ok) {\n throw new Error(\n readString(data?.error) || `Figma asset upload failed with ${response.status}`\n );\n }\n\n const storageKey = readString(data?.storageKey) ?? readString(data?.r2Key);\n const imageUrl = readString(data?.imageUrl) ?? readString(data?.publicUrl);\n if (!storageKey || !imageUrl) {\n throw new Error('Figma asset upload response is missing image URL.');\n }\n\n return { storageKey, imageUrl };\n}\n\nfunction createAssetUploadUrl(\n endpoint: string,\n params: {\n imageFormat: ReviewFigmaImageFormat;\n imageId: string;\n projectId: string;\n }\n) {\n const base =\n typeof window !== 'undefined' ? window.location.origin : 'http://localhost';\n const url = new URL(endpoint, base);\n url.searchParams.set('projectId', params.projectId);\n url.searchParams.set('imageId', params.imageId);\n url.searchParams.set('imageFormat', params.imageFormat);\n return url.toString();\n}\n\nfunction createImageRow({\n asset,\n fileKey,\n id,\n imageUrl,\n input,\n nodeId,\n now,\n order,\n storageKey,\n}: {\n asset: ReviewFigmaImageAssetInput;\n fileKey: string;\n id: string;\n imageUrl: string;\n input: AddReviewFigmaImageInput;\n nodeId: string;\n now: string;\n order: number;\n storageKey: string;\n}): ReviewFigmaRemoteImageRow {\n const target = input.target;\n const targetKey = getReviewFigmaImageTargetKey(target);\n\n return {\n id,\n project_id: target.projectId,\n target_key: targetKey,\n target,\n target_type: target.type,\n page_url: target.type === 'route' ? target.pageUrl : null,\n viewport_label: target.type === 'route' ? target.viewport?.label ?? null : null,\n viewport_width: target.type === 'route' ? target.viewport?.width ?? null : null,\n viewport_height: target.type === 'route' ? target.viewport?.height ?? null : null,\n viewport_scope: target.type === 'route' ? target.viewport?.scope ?? null : null,\n slot: target.type === 'route' ? target.slot ?? null : null,\n figma_url: input.figmaUrl,\n file_key: fileKey,\n node_id: nodeId,\n image_url: imageUrl,\n image_format: asset.imageFormat,\n mime_type: asset.mimeType,\n storage_key: storageKey,\n label: normalizeOptionalText(input.label) ?? null,\n sort_order: order,\n width: asset.width ?? null,\n height: asset.height ?? null,\n byte_size: asset.byteSize ?? null,\n created_at: now,\n updated_at: now,\n };\n}\n\nfunction createUpdatePatch(patch: UpdateReviewFigmaImageInput) {\n return {\n ...(patch.label !== undefined\n ? { label: normalizeOptionalText(patch.label) ?? null }\n : {}),\n ...(typeof patch.order === 'number' && Number.isFinite(patch.order)\n ? { sort_order: patch.order }\n : {}),\n updated_at: new Date().toISOString(),\n };\n}\n\nasync function getNextImageOrder(\n listImages: (target: ReviewFigmaImageTarget) => Promise<ReviewFigmaImage[]>,\n target: ReviewFigmaImageTarget\n) {\n const images = await listImages(target);\n return images.length\n ? Math.max(...images.map((image) => image.order)) + 1\n : 0;\n}\n\nfunction rowToFigmaImage(row: ReviewFigmaRemoteImageRow): ReviewFigmaImage {\n return {\n id: row.id,\n projectId: row.project_id,\n target: row.target,\n figmaUrl: row.figma_url,\n fileKey: row.file_key,\n nodeId: row.node_id,\n imageUrl: row.image_url,\n imageFormat: row.image_format,\n mimeType: row.mime_type,\n label: row.label ?? undefined,\n order: row.sort_order,\n storageKey: row.storage_key,\n width: row.width ?? undefined,\n height: row.height ?? undefined,\n byteSize: row.byte_size ?? undefined,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nfunction decodeAssetDataUrl(asset: ReviewFigmaImageAssetInput) {\n const match = asset.dataUrl.match(/^data:([^;,]+);base64,(.*)$/);\n if (!match) throw new Error('Valid Figma image asset data URL is required.');\n\n const mimeType = match[1]?.trim();\n if (!mimeType || mimeType !== asset.mimeType) {\n throw new Error('Figma image asset MIME type mismatch.');\n }\n\n const binary = globalThis.atob(match[2] ?? '');\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n\n return {\n blob: new Blob([bytes], { type: mimeType }),\n mimeType,\n };\n}\n\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message: string\n) {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<T>((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error(message)), timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutId) clearTimeout(timeoutId);\n }\n}\n\nfunction readRemoteFigmaToken(provider: ReviewFigmaRemoteTokenProvider) {\n const token = typeof provider === 'function' ? provider() : provider;\n if (typeof token === 'string' && token.trim()) return token.trim();\n return readStoredFigmaToken();\n}\n\nfunction readStoredFigmaToken() {\n if (typeof window === 'undefined') return '';\n\n try {\n return window.localStorage.getItem(FIGMA_TOKEN_STORAGE_KEY)?.trim() || '';\n } catch {\n return '';\n }\n}\n\nfunction createFigmaImageId() {\n const id =\n globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2);\n return `figma_${id.replace(/[^A-Za-z0-9_-]+/g, '-')}`;\n}\n\nfunction normalizeOptionalText(value: string | null | undefined) {\n if (typeof value !== 'string') return undefined;\n return value.trim() || undefined;\n}\n\nfunction readString(value: unknown) {\n return typeof value === 'string' && value.trim() ? value.trim() : null;\n}\n\nfunction throwRemoteStoreError(error: unknown, action: string): never {\n const source = error as {\n code?: unknown;\n details?: unknown;\n hint?: unknown;\n message?: unknown;\n };\n const message = readString(source.message) ?? `Remote Figma image ${action} failed.`;\n const code = readString(source.code);\n const details = readString(source.details);\n const hint = readString(source.hint);\n const suffix = [code, details, hint].filter(Boolean).join(' / ');\n\n throw new Error(suffix ? `${message} (${suffix})` : message);\n}\n"],"mappings":"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","names":[]}