11import { openSelectedProjectBrowser } from "./actions-browser.js"
22import { openSelectedProjectDatabaseEditor } from "./actions-databases.js"
3+ import { readEventPayloadString } from "./actions-event-payload.js"
34import { appendOutputLine , appendOutputLineHandler , notifyProjectEventRateLimit } from "./actions-output.js"
45import { openSelectedProjectPort } from "./actions-port-forwards.js"
56import {
@@ -13,9 +14,9 @@ import {
1314} from "./actions-shared.js"
1415import { loadSelectedProjectTasks } from "./actions-tasks.js"
1516import {
17+ type ApiEvent ,
1618 applyAllProjects ,
1719 applyProject ,
18- type ApiEvent ,
1920 deleteProject ,
2021 downAllProjects ,
2122 downProject ,
@@ -78,42 +79,39 @@ const resolveProjectTerminalKey = (
7879 return null
7980}
8081
81- const randomHex = ( bytes : number ) : string => {
82- const getRandomValues = globalThis . crypto ?. getRandomValues
83- if ( typeof getRandomValues === "function" ) {
84- const values = new Uint8Array ( bytes )
85- getRandomValues . call ( globalThis . crypto , values )
86- return Array . from ( values , ( value ) => value . toString ( 16 ) . padStart ( 2 , "0" ) ) . join ( "" )
87- }
82+ type ProjectCrypto = Crypto & {
83+ readonly randomUUID ?: ( ) => string
84+ }
8885
89- let fallback = ""
90- while ( fallback . length < bytes * 2 ) {
91- fallback += Math . floor ( Math . random ( ) * 0x1_0000_0000 )
92- . toString ( 16 )
93- . padStart ( 8 , "0" )
94- }
95- return fallback . slice ( 0 , bytes * 2 )
86+ const randomHex = ( bytes : number ) : string => {
87+ const values = new Uint8Array ( bytes )
88+ globalThis . crypto . getRandomValues ( values )
89+ return Array . from ( values , ( value ) => value . toString ( 16 ) . padStart ( 2 , "0" ) ) . join ( "" )
9690}
9791
9892const createPendingTerminalSessionId = ( ) : string => {
99- const randomUUID = globalThis . crypto ?. randomUUID
100- if ( typeof randomUUID === "function" ) {
101- return randomUUID . call ( globalThis . crypto )
93+ const crypto = globalThis . crypto as ProjectCrypto
94+ if ( typeof crypto . randomUUID === "function" ) {
95+ return crypto . randomUUID ( )
10296 }
10397
10498 return `pending-${ Date . now ( ) . toString ( 16 ) } -${ randomHex ( 8 ) } `
10599}
106100
107- const readEventPayloadString = (
108- event : ApiEvent ,
109- key : string
110- ) : string | null => {
111- const payload = event . payload
112- if ( payload === null || typeof payload !== "object" || Array . isArray ( payload ) ) {
113- return null
114- }
115- const value = Object . entries ( payload ) . find ( ( [ name ] ) => name === key ) ?. [ 1 ]
116- return typeof value === "string" ? value : null
101+ type ProjectActiveTerminalSessionArgs = Omit <
102+ Parameters < typeof buildProjectActiveTerminalSession > [ 0 ] ,
103+ "onExit" | "onReady"
104+ >
105+
106+ const addProjectTerminalSession = (
107+ context : BrowserActionContext ,
108+ args : ProjectActiveTerminalSessionArgs
109+ ) => {
110+ context . addTerminalSession ( buildProjectActiveTerminalSession ( {
111+ ...args ,
112+ onExit : context . reloadDashboard ,
113+ onReady : context . reloadDashboard
114+ } ) )
117115}
118116
119117const readTerminalSessionCreatedId = (
@@ -188,6 +186,11 @@ export const connectProjectById = (
188186 stream ?. close ( )
189187 stream = null
190188 }
189+ const showPendingTerminalError = ( error : string ) => {
190+ pendingSessionFinalized = true
191+ appendOutputLine ( context , `[error] ${ error } ` )
192+ context . addTerminalSession ( renderPendingTerminalSession ( error , "error" ) )
193+ }
191194 const attachCreatedSession = ( sessionId : string ) => {
192195 if ( attachedSessionId !== null ) {
193196 return
@@ -198,23 +201,19 @@ export const connectProjectById = (
198201 effect : loadProjectTerminalSession ( resolvedProjectKey , sessionId ) ,
199202 label : "Attaching SSH terminal" ,
200203 onFailure : ( error ) => {
201- pendingSessionFinalized = true
202- appendOutputLine ( context , `[error] ${ error } ` )
203- context . addTerminalSession ( renderPendingTerminalSession ( error , "error" ) )
204+ showPendingTerminalError ( error )
204205 closeStream ( )
205206 } ,
206207 onSuccess : ( session ) => {
207208 pendingSessionFinalized = true
208209 context . reloadDashboard ( )
209210 context . closeTerminalSession ( pendingSessionId )
210- context . addTerminalSession ( buildProjectActiveTerminalSession ( {
211- onExit : context . reloadDashboard ,
212- onReady : context . reloadDashboard ,
211+ addProjectTerminalSession ( context , {
213212 projectDisplayName,
214213 projectId,
215214 projectKey : resolvedProjectKey ,
216215 session
217- } ) )
216+ } )
218217 context . setMessage ( `Project is ready. SSH terminal is connecting for ${ projectDisplayName } .` )
219218 closeStream ( )
220219 }
@@ -225,9 +224,7 @@ export const connectProjectById = (
225224 effect : startProjectTerminalSession ( resolvedProjectKey , pendingSessionId ) ,
226225 label : "Opening SSH terminal" ,
227226 onFailure : ( error ) => {
228- pendingSessionFinalized = true
229- appendOutputLine ( context , `[error] ${ error } ` )
230- context . addTerminalSession ( renderPendingTerminalSession ( error , "error" ) )
227+ showPendingTerminalError ( error )
231228 } ,
232229 onSuccess : ( accepted ) => {
233230 appendOutputLine ( context , `[ssh.prepare] SSH terminal request accepted (${ accepted . requestId } )` )
@@ -237,9 +234,7 @@ export const connectProjectById = (
237234 onEvent : ( event ) => {
238235 const failure = readTerminalStartupFailure ( event , accepted . requestId )
239236 if ( failure !== null ) {
240- pendingSessionFinalized = true
241- appendOutputLine ( context , `[error] ${ failure } ` )
242- context . addTerminalSession ( renderPendingTerminalSession ( failure , "error" ) )
237+ showPendingTerminalError ( failure )
243238 context . setMessage ( failure )
244239 closeStream ( )
245240 return
@@ -306,14 +301,12 @@ export const attachProjectTerminalById = (
306301 effect : loadProjectTerminalSession ( resolvedProjectKey , sessionId ) ,
307302 label : "Attaching SSH terminal" ,
308303 onSuccess : ( session ) => {
309- context . addTerminalSession ( buildProjectActiveTerminalSession ( {
310- onExit : context . reloadDashboard ,
311- onReady : context . reloadDashboard ,
304+ addProjectTerminalSession ( context , {
312305 projectDisplayName,
313306 projectId,
314307 projectKey : resolvedProjectKey ,
315308 session
316- } ) )
309+ } )
317310 context . setMessage ( `Attached SSH terminal for ${ projectDisplayName } .` )
318311 }
319312 } )
0 commit comments