1- // Determine if we are on the test or production origins
2- const isTest = window . location . origin === 'https://test.neurite.network' ;
3- const isProd = window . location . origin === 'https://neurite.network' ;
1+ window . NeuriteEnv = {
2+ isProd : window . location . origin === 'https://neurite.network' ,
3+ isTest : window . location . origin === 'https://test.neurite.network' ,
4+ isElectron : window . startedViaElectron === true ,
5+ isLocalhostFrontend : window . location . origin === 'http://localhost:8080' ,
6+ isLocalFileFrontend : window . location . origin === 'null' ,
7+
8+ get isElectronWithLocalFrontend ( ) {
9+ return this . isElectron && ( this . isLocalhostFrontend || this . isLocalFileFrontend ) ;
10+ } ,
11+
12+ // Used for request fallback or redirect logic
13+ get baseUrl ( ) {
14+ if ( this . isProd ) return 'https://neurite.network' ;
15+ if ( this . isTest ) return 'https://test.neurite.network' ;
16+ return null ; // Electron-local and dev-hosted must proxy
17+ }
18+ }
19+
20+ function neuriteOriginCheck ( ) {
21+ const { isProd, isTest, isElectron } = window . NeuriteEnv ;
422
5- // Set the base URL or null if not on the test or production origins
6- const NEURITE_BASE_URL = isTest
7- ? 'https://test.neurite.network'
8- : isProd
9- ? 'https://neurite.network'
10- : null ;
23+ const isValidEnvironment = isProd || isTest || isElectron ;
24+ if ( isValidEnvironment ) return ;
25+
26+ alert ( 'Please access Neurite via neurite.network or the official app.' ) ;
27+ throw new Error ( 'Blocked request: invalid origin' ) ;
28+ }
1129
1230class NeuriteBackend {
1331 constructor ( ) {
14- this . baseUrl = NEURITE_BASE_URL ;
32+ this . baseUrl = window . NeuriteEnv . baseUrl ;
1533 }
1634
17- // General method for making API calls
1835 async request ( endpoint , options = { } ) {
19- neuriteOriginCheck ( ) ; // Check origin before making the request
36+ const isStreaming = options . stream === true ;
37+ neuriteOriginCheck ( ) ;
2038
21- const url = `${ this . baseUrl } /api${ endpoint } ` ;
22- const defaultOptions = {
23- credentials : 'include' , // Include cookies
39+ const url = this . baseUrl ? `${ this . baseUrl } /api ${ endpoint } ` : ` /api${ endpoint } `;
40+ const requestOptions = {
41+ credentials : 'include' ,
2442 headers : {
2543 'Content-Type' : 'application/json' ,
2644 ...( options . headers || { } )
2745 } ,
2846 ...options
2947 } ;
30-
48+
3149 try {
32- const response = await fetch ( url , defaultOptions ) ;
33-
34- if ( response . status === 401 ) {
35- if ( options . handleUnauthorized ) {
36- // Let the caller handle the unauthorized error
37- return response ;
38- } else {
39- // Use the global unauthorized handler
40- handleNeuriteUnauthorized ( ) ;
41- }
42- }
43-
44- // Optionally handle other status codes here
45-
46- return response ;
47- } catch ( error ) {
48- console . error ( `API request to ${ url } failed:` , error ) ;
49- throw error ;
50+ const response = window . NeuriteEnv . isElectronWithLocalFrontend
51+ ? await this . #electronRequest( endpoint , requestOptions , isStreaming )
52+ : await fetch ( url , requestOptions ) ;
53+
54+ return this . #handleResponse( response , options . handleUnauthorized ) ;
55+ } catch ( err ) {
56+ Logger . err ( `API request to ${ url } failed:` , err ) ;
57+ throw err ;
5058 }
5159 }
5260
53- // Example GET request
5461 async get ( endpoint , options = { } ) {
5562 return this . request ( endpoint , { method : 'GET' , ...options } ) ;
5663 }
5764
58- // Example POST request
5965 async post ( endpoint , body , options = { } ) {
6066 return this . request ( endpoint , {
6167 method : 'POST' ,
6268 body : JSON . stringify ( body ) ,
6369 ...options
6470 } ) ;
6571 }
66- }
6772
73+ async #handleResponse( response , handleUnauthorized ) {
74+ if ( response . status === 401 ) {
75+ if ( handleUnauthorized ) return response ;
76+ return handleNeuriteUnauthorized ( ) ;
77+ }
6878
69- // Instantiate and make it globally accessible
70- window . NeuriteBackend = new NeuriteBackend ( ) ;
79+ return response ;
80+ }
81+
82+ async #electronRequest( endpoint , requestOptions , isStreaming ) {
83+ if ( isStreaming ) {
84+ const id = crypto . randomUUID ( ) ;
85+ const encoder = new TextEncoder ( ) ;
86+
87+ const stream = new ReadableStream ( {
88+ start ( controller ) {
89+ const onChunk = ( event , data ) => {
90+ if ( data . id !== id ) return ;
91+
92+ if ( data . chunk ) controller . enqueue ( encoder . encode ( data . chunk ) ) ;
93+ if ( data . done ) {
94+ controller . close ( ) ;
95+ window . electronAPI . _removeStreamListener ( onChunk ) ;
96+ }
97+ if ( data . error ) {
98+ controller . error ( new Error ( data . error ) ) ;
99+ window . electronAPI . _removeStreamListener ( onChunk ) ;
100+ }
101+ } ;
102+ window . electronAPI . _addStreamListener ( onChunk ) ;
103+ }
104+ } ) ;
105+
106+ window . electronAPI . sendStreamRequest ( id , `/api${ endpoint } ` , requestOptions ) ;
71107
108+ return new Response ( stream , {
109+ headers : { 'Content-Type' : 'application/json' }
110+ } ) ;
111+ }
112+
113+ const response = await window . electronAPI . secureFetch ( endpoint , requestOptions ) ;
114+ return {
115+ ok : response . ok ,
116+ status : response . status ,
117+ json : async ( ) => response . data
118+ } ;
119+ }
120+ }
121+
122+ window . NeuriteBackend = new NeuriteBackend ( ) ;
72123
73124
74125// neuritePanel.js
@@ -103,29 +154,29 @@ class NeuritePanel {
103154 if ( storedEmail && emailDisplay ) {
104155 emailDisplay . textContent = storedEmail ;
105156 } else if ( ! emailDisplay ) {
106- console . warn ( 'Email display element not found.' ) ;
157+ Logger . warn ( 'Email display element not found.' ) ;
107158 }
108159
109160 this . setupTabEventListeners ( ) ;
110161
111162 if ( this . addFundsButton ) {
112163 this . addFundsButton . addEventListener ( 'click' , ( ) => this . balanceHandler . addFunds ( ) ) ;
113164 } else {
114- console . error ( 'Add funds button not found.' ) ;
165+ Logger . err ( 'Add funds button not found.' ) ;
115166 }
116167
117168 if ( this . signOutButton ) {
118169 this . signOutButton . addEventListener ( 'click' , signOut ) ;
119170 } else {
120- console . error ( 'Sign out button not found.' ) ;
171+ Logger . err ( 'Sign out button not found.' ) ;
121172 }
122173
123174 // Initialize Delete Account Button
124175 this . deleteAccountButton = document . getElementById ( 'delete-account-btn' ) ;
125176 if ( this . deleteAccountButton ) {
126177 this . deleteAccountButton . addEventListener ( 'click' , ( ) => this . handleDeleteAccount ( ) ) ;
127178 } else {
128- console . error ( 'Delete Account button not found.' ) ;
179+ Logger . err ( 'Delete Account button not found.' ) ;
129180 }
130181 }
131182
@@ -148,7 +199,7 @@ class NeuritePanel {
148199 } ) ;
149200 } ) ;
150201 } else {
151- console . error ( `Label for ${ labelId } not found.` ) ;
202+ Logger . err ( `Label for ${ labelId } not found.` ) ;
152203 }
153204 } ) ;
154205 }
@@ -173,11 +224,11 @@ class NeuritePanel {
173224 // Update local storage
174225 localStorage . setItem ( 'userBalance' , balance ) ;
175226 } catch ( error ) {
176- console . error ( 'Error fetching balance:' , error ) ;
227+ Logger . err ( 'Error fetching balance:' , error ) ;
177228 if ( this . balanceDisplay ) {
178229 this . balanceDisplay . textContent = 'error' ;
179230 } else {
180- console . warn ( 'Balance display element not found. Cannot display error.' ) ;
231+ Logger . warn ( 'Balance display element not found. Cannot display error.' ) ;
181232 }
182233 this . updateBalanceBar ( 0 ) ;
183234 return ;
@@ -209,7 +260,7 @@ class NeuritePanel {
209260 if ( this . balanceDisplay ) {
210261 this . balanceDisplay . textContent = `$${ safeBalance . toFixed ( 2 ) } ` ;
211262 } else {
212- //console .warn('Balance display element not found. Skipping balance display update.');
263+ //Logger .warn('Balance display element not found. Skipping balance display update.');
213264 }
214265
215266 // Update balance bar if element exists
@@ -247,7 +298,7 @@ class NeuritePanel {
247298 updateSignInState ( ) ;
248299 }
249300 } catch ( error ) {
250- console . error ( 'Delete Account Error:' , error ) ;
301+ Logger . err ( 'Delete Account Error:' , error ) ;
251302 alert ( `Error deleting account: ${ error . message } ` ) ;
252303 this . deleteAccountButton . disabled = false ;
253304 }
@@ -259,7 +310,7 @@ class NeuritePanel {
259310 if ( this . balanceBar ) {
260311 this . balanceBar . style . width = `${ percentage } %` ;
261312 } else {
262- //console .warn('Balance bar element not found. Skipping balance bar update.');
313+ //Logger .warn('Balance bar element not found. Skipping balance bar update.');
263314 }
264315 }
265316
@@ -352,7 +403,7 @@ class BalanceHandler {
352403 const data = await response . json ( ) ;
353404 return data . balance ;
354405 } catch ( error ) {
355- console . error ( 'Error fetching balance:' , error ) ;
406+ Logger . err ( 'Error fetching balance:' , error ) ;
356407 throw error ;
357408 }
358409 }
@@ -370,7 +421,7 @@ class BalanceHandler {
370421 const data = await response . json ( ) ;
371422 return data . sessionId ;
372423 } catch ( error ) {
373- console . error ( 'Error creating checkout session:' , error ) ;
424+ Logger . err ( 'Error creating checkout session:' , error ) ;
374425 throw error ;
375426 }
376427 }
0 commit comments