@antigenic-oss/paint 0.2.8 → 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.
@@ -1330,6 +1330,11 @@ function getInspectorCode(): string {
1330
1330
  }
1331
1331
  var meNewSelector = generateSelectorPath(meEl);
1332
1332
  var meActualIndex = Array.from(meNewParent.children).indexOf(meEl);
1333
+ var meAttrs = {};
1334
+ for (var mai = 0; mai < meEl.attributes.length; mai++) {
1335
+ var ma = meEl.attributes[mai];
1336
+ meAttrs[ma.name] = ma.value;
1337
+ }
1333
1338
  send({
1334
1339
  type: 'ELEMENT_MOVED',
1335
1340
  payload: {
@@ -1338,7 +1343,13 @@ function getInspectorCode(): string {
1338
1343
  oldParentSelectorPath: meOldParentSelector,
1339
1344
  newParentSelectorPath: msg.payload.newParentSelectorPath,
1340
1345
  oldIndex: meOldIndex,
1341
- newIndex: meActualIndex
1346
+ newIndex: meActualIndex,
1347
+ tagName: meEl.tagName.toLowerCase(),
1348
+ className: meEl.className && typeof meEl.className === 'string' ? meEl.className : null,
1349
+ elementId: meEl.id || null,
1350
+ innerText: (meEl.innerText || '').substring(0, 500) || null,
1351
+ attributes: meAttrs,
1352
+ computedStyles: getComputedStylesForElement(meEl)
1342
1353
  }
1343
1354
  });
1344
1355
  if (selectedElement === meEl) {
@@ -0,0 +1,149 @@
1
+ import { type NextRequest, NextResponse } from 'next/server'
2
+
3
+ /**
4
+ * Lightweight server-side proxy for the SW proxy.
5
+ * Fetches from the target localhost server and returns the raw response
6
+ * (no script stripping, no inspector injection — the SW handles all that).
7
+ * This exists because the SW runs in the browser and can't fetch cross-origin
8
+ * (localhost:3000) without CORS headers from the target.
9
+ */
10
+
11
+ const STRIP_HEADERS = new Set([
12
+ 'content-encoding',
13
+ 'transfer-encoding',
14
+ 'cross-origin-embedder-policy',
15
+ 'cross-origin-opener-policy',
16
+ 'cross-origin-resource-policy',
17
+ 'content-security-policy',
18
+ 'content-security-policy-report-only',
19
+ 'x-frame-options',
20
+ ])
21
+
22
+ async function handler(
23
+ request: NextRequest,
24
+ { params }: { params: Promise<{ path?: string[] }> },
25
+ ) {
26
+ const targetUrl = request.headers.get('x-sw-target')
27
+ if (!targetUrl) {
28
+ return new NextResponse('Missing x-sw-target header', { status: 400 })
29
+ }
30
+
31
+ // Validate localhost only
32
+ try {
33
+ const parsed = new URL(targetUrl)
34
+ if (
35
+ parsed.hostname !== 'localhost' &&
36
+ parsed.hostname !== '127.0.0.1'
37
+ ) {
38
+ return new NextResponse('Only localhost targets allowed', { status: 403 })
39
+ }
40
+ } catch {
41
+ return new NextResponse('Invalid target URL', { status: 400 })
42
+ }
43
+
44
+ const { path } = await params
45
+ const targetPath = path ? `/${path.join('/')}` : '/'
46
+ const targetOrigin = new URL(targetUrl).origin
47
+ const search = request.nextUrl.search
48
+ const fetchUrl = targetOrigin + targetPath + search
49
+
50
+ try {
51
+ // Forward all request headers to the target server. This ensures RSC
52
+ // headers (RSC, Next-Router-State-Tree, Next-Router-Prefetch), auth
53
+ // headers, Supabase headers, and any custom API headers reach the target.
54
+ // Only skip headers that must reflect the actual target or are internal.
55
+ const SKIP_REQUEST_HEADERS = new Set([
56
+ 'host',
57
+ 'origin',
58
+ 'referer',
59
+ 'connection',
60
+ 'x-sw-target',
61
+ 'x-forwarded-for',
62
+ 'x-forwarded-host',
63
+ 'x-forwarded-proto',
64
+ 'x-forwarded-port',
65
+ 'x-invoke-path',
66
+ 'x-invoke-query',
67
+ 'x-middleware-invoke',
68
+ 'x-middleware-prefetch',
69
+ ])
70
+ const forwardHeaders: Record<string, string> = {}
71
+ request.headers.forEach((value, key) => {
72
+ if (!SKIP_REQUEST_HEADERS.has(key.toLowerCase())) {
73
+ forwardHeaders[key] = value
74
+ }
75
+ })
76
+
77
+ const init: RequestInit = {
78
+ method: request.method,
79
+ headers: forwardHeaders,
80
+ redirect: 'manual',
81
+ }
82
+ // Forward body for non-GET/HEAD requests
83
+ if (request.method !== 'GET' && request.method !== 'HEAD') {
84
+ init.body = request.body
85
+ // @ts-expect-error -- Node fetch supports duplex for streaming body
86
+ init.duplex = 'half'
87
+ }
88
+
89
+ // Follow redirects manually so we can track the final URL
90
+ let response = await fetch(fetchUrl, init)
91
+ let finalUrl: string | null = null
92
+ let redirectCount = 0
93
+ while (
94
+ redirectCount < 10 &&
95
+ response.status >= 300 &&
96
+ response.status < 400 &&
97
+ response.headers.get('location')
98
+ ) {
99
+ const location = response.headers.get('location')!
100
+ const redirectTo = new URL(location, fetchUrl).href
101
+ finalUrl = redirectTo
102
+ response = await fetch(redirectTo, {
103
+ headers: forwardHeaders,
104
+ redirect: 'manual',
105
+ })
106
+ redirectCount++
107
+ }
108
+
109
+ // Copy headers, stripping security headers
110
+ const responseHeaders = new Headers()
111
+ for (const [key, value] of response.headers.entries()) {
112
+ if (!STRIP_HEADERS.has(key.toLowerCase())) {
113
+ responseHeaders.set(key, value)
114
+ }
115
+ }
116
+ responseHeaders.delete('content-length')
117
+
118
+ // Forward set-cookie headers from the target (auth tokens, sessions)
119
+ const setCookies = response.headers.getSetCookie?.()
120
+ if (setCookies?.length) {
121
+ for (const sc of setCookies) {
122
+ responseHeaders.append('set-cookie', sc)
123
+ }
124
+ }
125
+
126
+ // If the target redirected, tell the SW the final URL so the navigation
127
+ // blocker can set the correct path (prevents hydration mismatch).
128
+ if (finalUrl) {
129
+ responseHeaders.set('x-sw-final-url', finalUrl)
130
+ }
131
+
132
+ return new NextResponse(response.body, {
133
+ status: response.status,
134
+ headers: responseHeaders,
135
+ })
136
+ } catch (err) {
137
+ return new NextResponse(
138
+ `Failed to fetch from ${fetchUrl}: ${err instanceof Error ? err.message : String(err)}`,
139
+ { status: 502 },
140
+ )
141
+ }
142
+ }
143
+
144
+ export const GET = handler
145
+ export const POST = handler
146
+ export const PUT = handler
147
+ export const PATCH = handler
148
+ export const DELETE = handler
149
+ export const OPTIONS = handler
@@ -6,7 +6,7 @@ const NAV_ITEMS = [
6
6
  { id: 'how-it-works', label: 'How It Works' },
7
7
  { id: 'use-cases', label: 'Use Cases' },
8
8
  { id: 'quick-start', label: 'Quick Start' },
9
- { id: 'framework-guides', label: 'Framework Guides' },
9
+ { id: 'framework-guides', label: 'Compatibility' },
10
10
  { id: 'troubleshooting', label: 'Troubleshooting' },
11
11
  { id: 'faq', label: 'FAQ' },
12
12
  ] as const