@@ -12,13 +12,15 @@ const port = 3000;
1212
1313const webflowDomain = process . argv [ 2 ] || 'test-e93bfd.webflow.io' ;
1414
15+ const workers = [ ] ;
1516const importedWorkers = { } ;
1617
1718/**
19+ * @param {string } workerName
1820 * @param {string } workerPath
1921 * @returns {Promise<Function> }
2022 */
21- async function importWorker ( workerPath ) {
23+ async function importWorker ( workerName , workerPath ) {
2224 const workerContent = ( await fs . promises . readFile ( workerPath , 'utf8' ) )
2325 . toString ( )
2426 . replaceAll ( 'webflow.bitrise.io' , webflowDomain )
@@ -28,14 +30,15 @@ async function importWorker(workerPath) {
2830 )
2931 . replaceAll ( / \/ \* ( .| [ \n \r ] ) * ?\* \/ / gm, '' )
3032 . replaceAll ( / \/ \/ .* $ / g, '' ) ;
31- const workerName = `${ workerPath } -${ crypto . createHash ( 'md5' ) . update ( workerContent ) . digest ( 'hex' ) } ` ;
32- if ( ! importedWorkers [ workerName ] ) {
33+ const workerNameWithHash = `${ workerName } -${ crypto . createHash ( 'md5' ) . update ( workerContent ) . digest ( 'hex' ) } ` ;
34+ if ( ! importedWorkers [ workerNameWithHash ] ) {
3335 if ( workerContent . match ( / a d d E v e n t L i s t e n e r \( ' f e t c h ' , / ) ) {
3436 // Service Worker Syntax
3537 eval ( `(() => {
3638 function addEventListener(_, cb) {
37- importedWorkers['${ workerName } '] = { type: "Service" };
38- importedWorkers['${ workerName } '].handler = cb;
39+ importedWorkers['${ workerNameWithHash } '] = { type: "Service" };
40+ importedWorkers['${ workerNameWithHash } '].name = '${ workerName } ';
41+ importedWorkers['${ workerNameWithHash } '].handler = cb;
3942 };
4043 ${ workerContent }
4144 })();` ) ;
@@ -46,35 +49,82 @@ async function importWorker(workerPath) {
4649 ${ workerContent . replace (
4750 / e x p o r t d e f a u l t { / ,
4851 `
49- importedWorkers['${ workerName } '] = { type: "ES6 Module" };
50- importedWorkers['${ workerName } '].handler = {` ,
52+ importedWorkers['${ workerNameWithHash } '] = { type: "ES6 Module" };
53+ importedWorkers['${ workerNameWithHash } '].name = '${ workerName } ';
54+ importedWorkers['${ workerNameWithHash } '].handler = {` ,
5155 ) }
5256 })();` ) ;
5357 }
54- process . stdout . write ( `[info] Registered new ${ importedWorkers [ workerName ] . type } Worker: ${ workerName } \n` ) ;
58+ process . stdout . write ( `[info] Registered new Worker: ${ workerName } ( ${ importedWorkers [ workerNameWithHash ] . type } ) \n` ) ;
5559 }
56- return importedWorkers [ workerName ] ;
60+ return importedWorkers [ workerNameWithHash ] ;
61+ }
62+
63+ /**
64+ *
65+ * @param {string }dir
66+ */
67+ async function discoverWorkers ( dir ) {
68+ const entries = await fs . promises . readdir ( dir , { withFileTypes : true } ) ;
69+
70+ await Promise . all (
71+ entries . map ( async ( entry ) => {
72+ const fullPath = path . join ( dir , entry . name ) ;
73+
74+ if ( entry . isDirectory ( ) ) {
75+ await discoverWorkers ( fullPath ) ;
76+ } else if ( entry . name === 'wrangler.toml' ) {
77+ const tomlContent = await fs . promises . readFile ( fullPath , 'utf8' ) ;
78+ // Basic TOML parsing - you may want to use a proper TOML parser library
79+ const config = { } ;
80+ const lines = tomlContent . split ( '\n' ) ;
81+ lines . forEach ( ( line ) => {
82+ const match = line . match ( / ^ ( \w + ) \s * = \s * [ " ' ] ? ( [ ^ " ' \n ] + ) [ " ' ] ? / ) ;
83+ if ( match ) {
84+ const [ , key , value ] = match ;
85+ config [ key ] = value ;
86+ }
87+ } ) ;
88+
89+ workers . push ( {
90+ name : path . basename ( path . dirname ( fullPath ) ) ,
91+ path : fullPath ,
92+ config,
93+ } ) ;
94+
95+ process . stdout . write ( `[info] Found worker config: ${ fullPath } \n` ) ;
96+ }
97+ } ) ,
98+ ) ;
5799}
58100
59101/**
60102 * @param {URL } urlObject
61103 * @returns {Promise<{ type: string; handler: Function; }> }
62104 */
63105async function getWorker ( urlObject ) {
64- if ( urlObject . pathname . match ( / ^ \/ i n t e g r a t i o n s / ) ) {
65- return importWorker ( './src/js/integrations/worker.js' ) ;
66- }
67- if ( urlObject . pathname . match ( / ^ \/ c h a n g e l o g / ) ) {
68- return importWorker ( './src/js/changelog/worker.js' ) ;
106+ if ( workers . length === 0 ) {
107+ await discoverWorkers ( './src/js' ) ;
69108 }
70- if ( urlObject . pathname . match ( / ^ \/ s t a c k s / ) ) {
71- return importWorker ( './src/js/stacks/worker.js' ) ;
72- }
73- if ( urlObject . pathname . match ( / ^ \/ c a r e e r s \/ m a p s \/ / ) ) {
74- return importWorker ( './src/js/career-maps/worker.js' ) ;
109+
110+ const matchedWorker = workers . filter ( ( worker ) => {
111+ let routePattern = worker . config . route . replace ( 'bitrise.io' , '^' ) ;
112+ if ( routePattern . endsWith ( '*' ) ) {
113+ routePattern = routePattern . slice ( 0 , - 1 ) ;
114+ } else {
115+ routePattern = `${ routePattern } $` ;
116+ }
117+ return urlObject . pathname . match ( new RegExp ( routePattern ) ) ;
118+ } ) ;
119+
120+ if ( matchedWorker . length > 0 ) {
121+ const worker = matchedWorker [ 0 ] ;
122+ return importWorker ( worker . config . name , path . join ( path . dirname ( worker . path ) , worker . config . main ) ) ;
75123 }
124+
76125 return {
77126 type : 'ES6 Module' ,
127+ name : 'express-proxy' ,
78128 handler : {
79129 async fetch ( request ) {
80130 const url = new URL ( request . url ) ;
@@ -118,7 +168,7 @@ app.get(/\/.*/, async (req, res) => {
118168 } catch ( error ) {
119169 const requestHandler = await getWorker ( urlObject ) ;
120170
121- process . stdout . write ( `[info] Using request handler ${ requestHandler . type } \n` ) ;
171+ process . stdout . write ( `[info] Using request handler ${ requestHandler . name } ( ${ requestHandler . type } ) \n` ) ;
122172
123173 const fetchEvent = {
124174 request : {
@@ -128,6 +178,11 @@ app.get(/\/.*/, async (req, res) => {
128178 const response = await buffer ;
129179 res . statusCode = response . status ;
130180
181+ const responseAccessControlAllowOrigin = response . headers . get ( 'Access-Control-Allow-Origin' ) ;
182+ if ( responseAccessControlAllowOrigin )
183+ res . setHeader ( 'Access-Control-Allow-Origin' , responseAccessControlAllowOrigin ) ;
184+ const responseVary = response . headers . get ( 'Vary' ) ;
185+ if ( responseVary ) res . setHeader ( 'Vary' , responseVary ) ;
131186 const responseContentType = response . headers . get ( 'Content-Type' ) ;
132187 if ( responseContentType ) res . setHeader ( 'Content-Type' , response . headers . get ( 'Content-Type' ) ) ;
133188 const responseLocation = response . headers . get ( 'Location' ) ;
@@ -137,7 +192,7 @@ app.get(/\/.*/, async (req, res) => {
137192 responseLocation . replace ( webflowDomain , `${ hostname } :${ port } ` ) . replace ( 'https' , 'http' ) ,
138193 ) ;
139194
140- process . stdout . write ( `[info] Serving ${ response . url } with status ${ res . statusCode } \n` ) ;
195+ process . stdout . write ( `[info] Serving ${ urlObject . href } with status ${ res . statusCode } \n` ) ;
141196
142197 let text = ( await response . text ( ) )
143198 . replace ( "document.location.host === 'test-e93bfd.webflow.io'" , 'true' )
0 commit comments