@@ -4,13 +4,18 @@ import {
4
4
readableStreamFromIterable ,
5
5
SubProcess ,
6
6
type SubprocessErrorData ,
7
+ trace ,
8
+ context ,
9
+ Context ,
7
10
} from "../../deps.ts" ;
8
11
9
12
import { templateHtml , makeErrorResponse , HtmlHeaders } from '../../lib/request-handling.ts' ;
10
13
import { findModuleSlug , resolveModuleUrl } from "../../lib/resolve.ts" ;
11
14
import { computeGraph , renderGraph } from "./compute.ts" ;
12
15
13
- export async function * handleRequest ( req : Request , modSlug : string , args : URLSearchParams ) {
16
+ const tracer = trace . getTracer ( 'dependencies-of-api' ) ;
17
+
18
+ export async function handleRequest ( req : Request , modSlug : string , args : URLSearchParams ) {
14
19
if ( modSlug == '' ) {
15
20
const url = args . get ( 'url' ) ;
16
21
if ( ! url ) return ;
@@ -26,7 +31,7 @@ export async function *handleRequest(req: Request, modSlug: string, args: URLSea
26
31
27
32
const slug = await findModuleSlug ( url ) ;
28
33
const location = slug + ( args . toString ( ) ? `?${ args } ` : '' ) ;
29
- yield new Response ( `302: ${ location } ` , {
34
+ return new Response ( `302: ${ location } ` , {
30
35
status : 302 ,
31
36
headers : { location } ,
32
37
} ) ;
@@ -37,17 +42,13 @@ export async function *handleRequest(req: Request, modSlug: string, args: URLSea
37
42
38
43
switch ( args . get ( 'format' ) ) {
39
44
case 'json' :
40
- yield serveBufferedOutput ( req , computeGraph ( modUrl , args ) , 'application/json' ) ;
41
- return ;
45
+ return await serveBufferedOutput ( req , computeGraph ( modUrl , args ) , 'application/json' ) ;
42
46
case 'dot' :
43
- yield serveBufferedOutput ( req , computeGraph ( modUrl , args ) , 'text/plain; charset=utf-8' ) ;
44
- return ;
47
+ return await serveBufferedOutput ( req , computeGraph ( modUrl , args ) , 'text/plain; charset=utf-8' ) ;
45
48
case 'svg' :
46
- yield serveStreamingOutput ( req , renderGraph ( modUrl , [ "-Tsvg" ] , args ) , 'image/svg+xml' ) ;
47
- return ;
49
+ return await serveStreamingOutput ( req , renderGraph ( modUrl , [ "-Tsvg" ] , args ) , 'image/svg+xml' ) ;
48
50
case null :
49
- yield serveHtmlGraphPage ( req , modUrl , modSlug , args ) ;
50
- return ;
51
+ return await serveHtmlGraphPage ( req , modUrl , modSlug , args ) ;
51
52
}
52
53
}
53
54
@@ -75,56 +76,40 @@ async function serveStreamingOutput(req: Request, computation: Promise<SubProces
75
76
76
77
const hideLoadMsg = `<style type="text/css">#graph-waiting { display: none; }</style>` ;
77
78
78
- async function serveHtmlGraphPage ( req : Request , modUrl : string , modSlug : string , args : URLSearchParams ) {
79
- args . set ( 'font' , 'Archivo Narrow' ) ;
80
-
81
- // Render the basic page first, so we can error more cleanly if that fails
82
- let pageHtml = '' ;
79
+ async function renderModuleToHtml ( modUrl : string , args : URLSearchParams ) {
83
80
try {
84
- pageHtml = await templateHtml ( 'feat/dependencies-of/public.html' , {
85
- module_slug : entities . encode ( modSlug ) ,
86
- module_url : entities . encode ( modUrl ) ,
87
- export_prefix : entities . encode ( `${ req . url } ${ req . url . includes ( '?' ) ? '&' : '?' } format=` ) ,
88
- } ) ;
89
- } catch ( err ) {
90
- return makeErrorResponse ( err ) ;
91
- }
92
81
93
- const graphPromise = ( ( args . get ( 'renderer' ) === 'interactive' )
94
-
95
- ? computeGraph ( modUrl , args , 'dot' )
96
- . then ( data => {
97
- return `
98
- <div id="graph"></div>
99
- <script type="text/javascript" src="https://unpkg.com/[email protected] /standalone/umd/vis-network.min.js"></script>
100
- <script type="text/javascript" src="/interactive-graph.js"></script>
101
- <template type="text/plain" id="graphviz_data">\n${ data
102
- . replace ( / & / g, '&' )
103
- . replace ( / > / g, '>' )
104
- . replace ( / < / g, '<' )
105
- } </template>
106
- <script type="text/javascript">
107
- window.CreateModuleGraph(document.getElementById('graphviz_data').innerHTML
108
- .replace(/>/g, '>')
109
- .replace(/</g, '<')
110
- .replace(/&/g, '&'));
111
- </script>
112
- ` . replace ( / ^ { 10 } / gm, '' ) ;
113
- } )
114
-
115
- : renderGraph ( modUrl , [ "-Tsvg" ] , args )
116
- . then ( dotProc => dotProc . captureAllOutput ( ) )
117
- . then ( raw => {
118
- const fullSvg = new TextDecoder ( ) . decode ( raw ) ;
119
- const attrs = [ `id="graph"` ] ;
120
- const svgWidth = fullSvg . match ( / v i e w B o x = " (?: ( [ 0 - 9 . - ] + ) ) { 3 } / ) ?. [ 1 ] ;
121
- if ( svgWidth ) attrs . push ( `style="max-width: ${ parseInt ( svgWidth ) * 2 } px;"` ) ;
122
- return fullSvg
123
- . slice ( fullSvg . indexOf ( '<!--' ) )
124
- . replace ( / < s v g w i d t h = " [ ^ " ] + " h e i g h t = " [ ^ " ] + " / , '<svg ' + attrs . join ( ' ' ) ) ;
125
- } )
126
-
127
- ) . catch ( err => {
82
+ if ( args . get ( 'renderer' ) === 'interactive' ) {
83
+ const data = await computeGraph ( modUrl , args , 'dot' ) ;
84
+ return `
85
+ <div id="graph"></div>
86
+ <script type="text/javascript" src="https://unpkg.com/[email protected] /standalone/umd/vis-network.min.js"></script>
87
+ <script type="text/javascript" src="/interactive-graph.js"></script>
88
+ <template type="text/plain" id="graphviz_data">\n${ data
89
+ . replace ( / & / g, '&' )
90
+ . replace ( / > / g, '>' )
91
+ . replace ( / < / g, '<' )
92
+ } </template>
93
+ <script type="text/javascript">
94
+ window.CreateModuleGraph(document.getElementById('graphviz_data').innerHTML
95
+ .replace(/>/g, '>')
96
+ .replace(/</g, '<')
97
+ .replace(/&/g, '&'));
98
+ </script>
99
+ ` . replace ( / ^ { 8 } / gm, '' ) ;
100
+ }
101
+
102
+ const dotProc = await renderGraph ( modUrl , [ "-Tsvg" ] , args ) ;
103
+ const raw = await dotProc . captureAllOutput ( ) ;
104
+ const fullSvg = new TextDecoder ( ) . decode ( raw ) ;
105
+ const attrs = [ `id="graph"` ] ;
106
+ const svgWidth = fullSvg . match ( / v i e w B o x = " (?: ( [ 0 - 9 . - ] + ) ) { 3 } / ) ?. [ 1 ] ;
107
+ if ( svgWidth ) attrs . push ( `style="max-width: ${ parseInt ( svgWidth ) * 2 } px;"` ) ;
108
+ return fullSvg
109
+ . slice ( fullSvg . indexOf ( '<!--' ) )
110
+ . replace ( / < s v g w i d t h = " [ ^ " ] + " h e i g h t = " [ ^ " ] + " / , '<svg ' + attrs . join ( ' ' ) ) ;
111
+
112
+ } catch ( err ) {
128
113
if ( err . subproc ) {
129
114
const info = err . subproc as SubprocessErrorData ;
130
115
return `
@@ -140,7 +125,30 @@ async function serveHtmlGraphPage(req: Request, modUrl: string, modSlug: string,
140
125
}
141
126
console . error ( 'Graph computation error:' , err . stack ) ;
142
127
return `<div id="graph-error">${ entities . encode ( err . stack ) } </div>` ;
143
- } ) ;
128
+ }
129
+ }
130
+
131
+ async function serveHtmlGraphPage ( req : Request , modUrl : string , modSlug : string , args : URLSearchParams ) {
132
+ args . set ( 'font' , 'Archivo Narrow' ) ;
133
+
134
+ // Render the basic page first, so we can error more cleanly if that fails
135
+ let pageHtml = '' ;
136
+ try {
137
+ pageHtml = await templateHtml ( 'feat/dependencies-of/public.html' , {
138
+ module_slug : entities . encode ( modSlug ) ,
139
+ module_url : entities . encode ( modUrl ) ,
140
+ export_prefix : entities . encode ( `${ req . url } ${ req . url . includes ( '?' ) ? '&' : '?' } format=` ) ,
141
+ } ) ;
142
+ } catch ( err ) {
143
+ return makeErrorResponse ( err ) ;
144
+ }
145
+
146
+ const graphPromise = tracer . startActiveSpan ( 'Compute + Render Graph' , {
147
+ attributes : {
148
+ 'render.mod_url' : modUrl ,
149
+ 'render.params' : args . toString ( ) ,
150
+ } ,
151
+ } , context . active ( ) , span => renderModuleToHtml ( modUrl , args ) . finally ( ( ) => span . end ( ) ) ) ;
144
152
145
153
// Return the body in two parts, with a comment in between
146
154
return new Response ( readableStreamFromIterable ( ( async function * ( ) {
0 commit comments