@@ -2,14 +2,15 @@ import fs from 'node:fs/promises'
22import path from 'node:path'
33import { fileURLToPath } from 'node:url'
44import express from 'express'
5+ import type { Har } from 'har-format'
56import { PAGES } from './har-index'
67
78const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) )
89const app = express ( )
910const PORT = 3001
1011
1112// Store HAR json
12- const harCache = new Map < keyof typeof PAGES , any > ( )
13+ const harCache = new Map < keyof typeof PAGES , Har > ( )
1314
1415// Extract URL parts for location patching
1516function getUrlParts ( key : keyof typeof PAGES ) {
@@ -37,9 +38,9 @@ async function checkDevServer(): Promise<boolean> {
3738}
3839
3940// Load and cache HAR file
40- async function loadHar ( key : keyof typeof PAGES ) {
41+ async function loadHar ( key : keyof typeof PAGES ) : Promise < Har > {
4142 if ( harCache . has ( key ) ) {
42- return harCache . get ( key )
43+ return harCache . get ( key ) !
4344 }
4445
4546 const harPath = path . join ( __dirname , 'har' , `${ key } .har` )
@@ -53,7 +54,7 @@ async function loadHar(key: keyof typeof PAGES) {
5354Object . entries ( PAGES ) . forEach ( ( [ key , url ] ) => {
5455 const urlObj = new URL ( url )
5556 app . get ( urlObj . pathname , ( _req , res ) => {
56- res . redirect ( `/page /${ key } /gitcasso` )
57+ res . redirect ( `/har /${ key } /gitcasso` )
5758 } )
5859} )
5960
@@ -81,8 +82,8 @@ app.get('/', async (_req, res) => {
8182 <li>
8283 <div style="margin-bottom: 10px; font-weight: bold; color: #555;">${ basename } </div>
8384 <div style="display: flex; gap: 10px;">
84- <a href="/page /${ basename } " style="flex: 1; text-align: center;">🔍 Clean</a>
85- <a href="/page /${ basename } /gitcasso" style="flex: 1; text-align: center; ${ ! devServerRunning ? 'opacity: 0.5; pointer-events: none;' : '' } ">
85+ <a href="/har /${ basename } /clean " style="flex: 1; text-align: center;">🔍 Clean</a>
86+ <a href="/har /${ basename } /gitcasso" style="flex: 1; text-align: center; ${ ! devServerRunning ? 'opacity: 0.5; pointer-events: none;' : '' } ">
8687 🚀 Gitcasso-enabled
8788 </a>
8889 </div>
@@ -134,58 +135,20 @@ app.get('/', async (_req, res) => {
134135} )
135136
136137// Serve the main HTML page from HAR
137- app . get ( '/page /:key' , async ( req , res ) => {
138+ app . get ( '/har /:key/:mode(clean|gitcasso) ' , async ( req , res ) => {
138139 try {
139- const key = req . params . key as keyof typeof PAGES
140- if ( ! ( key in PAGES ) ) {
141- return res . status ( 400 ) . send ( 'Invalid key - not found in PAGES' )
142- }
143-
144- const harData = await loadHar ( key )
145-
146- // Find the main HTML response
147- const mainEntry = harData . log . entries . find (
148- ( entry : any ) =>
149- entry . request . url . includes ( 'github.com' ) &&
150- entry . response . content . mimeType ?. includes ( 'text/html' ) &&
151- entry . response . content . text ,
152- )
153-
154- if ( ! mainEntry ) {
155- return res . status ( 404 ) . send ( 'No HTML content found in HAR file' )
156- }
157-
158- let html = mainEntry . response . content . text
140+ const key = req . params [ 'key' ] as keyof typeof PAGES
141+ const mode = req . params [ 'mode' ] as 'clean' | 'gitcasso'
159142
160- // Replace external URLs with local asset URLs
161- html = html . replace (
162- / h t t p s : \/ \/ ( g i t h u b \. c o m | a s s e t s \. g i t h u b \. c o m | a v a t a r s \. g i t h u b u s e r c o n t e n t \. c o m | u s e r - i m a g e s \. g i t h u b u s e r c o n t e n t \. c o m ) / g,
163- `/asset/${ key } ` ,
164- )
165-
166- return res . send ( html )
167- } catch ( error ) {
168- console . error ( 'Error serving page:' , error )
169- return res . status ( 500 ) . send ( 'Error loading page' )
170- }
171- } )
172-
173- // Serve the main HTML page from HAR with Gitcasso content script injected
174- app . get ( '/page/:key/gitcasso' , async ( req , res ) => {
175- try {
176- const key = req . params . key as keyof typeof PAGES
177143 if ( ! ( key in PAGES ) ) {
178144 return res . status ( 400 ) . send ( 'Invalid key - not found in PAGES' )
179145 }
180146
181- // Get original URL parts for location patching
182- const urlParts = getUrlParts ( key )
183-
184147 const harData = await loadHar ( key )
185148
186149 // Find the main HTML response
187150 const mainEntry = harData . log . entries . find (
188- ( entry : any ) =>
151+ ( entry ) =>
189152 entry . request . url . includes ( 'github.com' ) &&
190153 entry . response . content . mimeType ?. includes ( 'text/html' ) &&
191154 entry . response . content . text ,
@@ -195,71 +158,77 @@ app.get('/page/:key/gitcasso', async (req, res) => {
195158 return res . status ( 404 ) . send ( 'No HTML content found in HAR file' )
196159 }
197160
198- let html = mainEntry . response . content . text
161+ let html = mainEntry . response . content . text !
199162
200163 // Replace external URLs with local asset URLs
201164 html = html . replace (
202165 / h t t p s : \/ \/ ( g i t h u b \. c o m | a s s e t s \. g i t h u b \. c o m | a v a t a r s \. g i t h u b u s e r c o n t e n t \. c o m | u s e r - i m a g e s \. g i t h u b u s e r c o n t e n t \. c o m ) / g,
203166 `/asset/${ key } ` ,
204167 )
205168
206- // Inject patched content script with location patching
207- const contentScriptTag = `
208- <script>
209- // Patch window.location before loading content script
210- console.log('Patching window.location to simulate original URL...');
211-
212- // Use history.pushState to change the pathname
213- window.history.pushState({}, '', '${ urlParts . pathname } ');
214-
215- console.log('Location patched:', {
216- hostname: window.location.hostname,
217- pathname: window.location.pathname,
218- href: window.location.href,
219- host: window.location.host
220- });
221-
222- // Fetch and patch the content script to remove webextension-polyfill issues
223- fetch('http://localhost:3000/.output/chrome-mv3-dev/content-scripts/content.js')
224- .then(response => response.text())
225- .then(code => {
226- console.log('Fetched content script, patching webextension-polyfill...');
227-
228- // Replace the problematic webextension-polyfill error check
229- const patchedCode = code.replace(
230- /throw new Error\\("This script should only be loaded in a browser extension\\."/g,
231- 'console.warn("Webextension-polyfill check bypassed for HAR testing"'
232- );
233-
234- // Mock necessary APIs before executing
235- window.chrome = window.chrome || {
236- runtime: {
237- getURL: (path) => 'chrome-extension://gitcasso-test/' + path,
238- onMessage: { addListener: () => {} },
239- sendMessage: () => Promise.resolve(),
240- id: 'gitcasso-test'
241- }
242- };
243- window.browser = window.chrome;
244-
245- // Execute the patched script
246- const script = document.createElement('script');
247- script.textContent = patchedCode;
248- document.head.appendChild(script);
249-
250- console.log('Gitcasso content script loaded with location patching for:', '${ urlParts . href } ');
251- })
252- .catch(error => {
253- console.error('Failed to load and patch content script:', error);
169+ // If gitcasso mode, inject content script
170+ if ( mode === 'gitcasso' ) {
171+ // Get original URL parts for location patching
172+ const urlParts = getUrlParts ( key )
173+
174+ // Inject patched content script with location patching
175+ const contentScriptTag = `
176+ <script>
177+ // Patch window.location before loading content script
178+ console.log('Patching window.location to simulate original URL...');
179+
180+ // Use history.pushState to change the pathname
181+ window.history.pushState({}, '', '${ urlParts . pathname } ');
182+
183+ console.log('Location patched:', {
184+ hostname: window.location.hostname,
185+ pathname: window.location.pathname,
186+ href: window.location.href,
187+ host: window.location.host
254188 });
255- </script>
256- `
189+
190+ // Fetch and patch the content script to remove webextension-polyfill issues
191+ fetch('http://localhost:3000/.output/chrome-mv3-dev/content-scripts/content.js')
192+ .then(response => response.text())
193+ .then(code => {
194+ console.log('Fetched content script, patching webextension-polyfill...');
195+
196+ // Replace the problematic webextension-polyfill error check
197+ const patchedCode = code.replace(
198+ /throw new Error\\("This script should only be loaded in a browser extension\\."/g,
199+ 'console.warn("Webextension-polyfill check bypassed for HAR testing"'
200+ );
201+
202+ // Mock necessary APIs before executing
203+ window.chrome = window.chrome || {
204+ runtime: {
205+ getURL: (path) => 'chrome-extension://gitcasso-test/' + path,
206+ onMessage: { addListener: () => {} },
207+ sendMessage: () => Promise.resolve(),
208+ id: 'gitcasso-test'
209+ }
210+ };
211+ window.browser = window.chrome;
212+
213+ // Execute the patched script
214+ const script = document.createElement('script');
215+ script.textContent = patchedCode;
216+ document.head.appendChild(script);
217+
218+ console.log('Gitcasso content script loaded with location patching for:', '${ urlParts . href } ');
219+ })
220+ .catch(error => {
221+ console.error('Failed to load and patch content script:', error);
222+ });
223+ </script>
224+ `
257225
258- // Insert script before closing body tag, or at the end if no body tag
259- if ( html . includes ( '</body>' ) ) {
260- html = html . replace ( '</body>' , `${ contentScriptTag } </body>` )
261- } else {
262- html += contentScriptTag
226+ // Insert script before closing body tag, or at the end if no body tag
227+ if ( html . includes ( '</body>' ) ) {
228+ html = html . replace ( '</body>' , `${ contentScriptTag } </body>` )
229+ } else {
230+ html += contentScriptTag
231+ }
263232 }
264233
265234 return res . send ( html )
@@ -281,7 +250,7 @@ app.get('/asset/:key/*', async (req, res) => {
281250 const harData = await loadHar ( key )
282251
283252 // Find matching asset in HAR
284- const assetEntry = harData . log . entries . find ( ( entry : any ) => {
253+ const assetEntry = harData . log . entries . find ( ( entry ) => {
285254 const url = new URL ( entry . request . url )
286255 return url . pathname === `/${ assetPath } ` || url . pathname . endsWith ( `/${ assetPath } ` )
287256 } )
@@ -292,13 +261,11 @@ app.get('/asset/:key/*', async (req, res) => {
292261
293262 const content = assetEntry . response . content
294263 const mimeType = content . mimeType || 'application/octet-stream'
295-
296264 res . set ( 'Content-Type' , mimeType )
297-
298265 if ( content . encoding === 'base64' ) {
299- return res . send ( Buffer . from ( content . text , 'base64' ) )
266+ return res . send ( Buffer . from ( content . text ! , 'base64' ) )
300267 } else {
301- return res . send ( content . text || '' )
268+ return res . send ( content . text ! )
302269 }
303270 } catch ( error ) {
304271 console . error ( 'Error serving asset:' , error )
0 commit comments