11< h3 > Request Builder</ h3 >
2- < div class ="request-builder " id ="request-builder "> </ div >
2+ < div class ="request-builder ">
3+ < label for ="method "> HTTP Method:</ label >
4+ < select id ="method ">
5+ < option value ="GET "> GET</ option >
6+ < option value ="POST "> POST</ option >
7+ < option value ="PUT "> PUT</ option >
8+ < option value ="DELETE "> DELETE</ option >
9+ < option value ="PATCH "> PATCH</ option >
10+ < option value ="OPTIONS "> OPTIONS</ option >
11+ < option value ="HEAD "> HEAD</ option >
12+ </ select >
13+
14+ < label for ="url "> URI:</ label >
15+ < input id ="url " type ="text " placeholder ="/echo ">
16+
17+ < label for ="bodyJSON "> JSON Body:</ label >
18+ < textarea id ="bodyJSON " rows ="8 " placeholder ='{"example":"value"} '> </ textarea >
19+
20+ < label > Headers:</ label >
21+ < div id ="headers-container ">
22+ <!-- Dynamic header entries go here -->
23+ </ div >
24+ < button id ="add-header "> Add Header</ button >
25+
26+ </ div >
327< h3 > NJS Function</ h3 >
428< div class ="njs-function " id ="editor "> </ div >
529< button id ="run-btn "> Simulate Request</ button >
@@ -12,29 +36,83 @@ <h3>NJS Function</h3>
1236< script type ="module ">
1337 import { getQuickJS } from "https://esm.sh/[email protected] " ; 1438
15- // Fetch the example js files, set by shortcode usage
16- const exampleResponse = await fetch ( "/njs/{{ .exampleRequest }}" ) ;
17- if ( ! exampleResponse . ok ) {
18- throw new Error ( `Failed to fetch {{ .exampleRequest }}: ${ exampleResponse . status } ` ) ;
39+ // Request builder stuff
40+ const methodEl = document . getElementById ( 'method' ) ;
41+ const urlEl = document . getElementById ( 'url' ) ;
42+ const bodyEl = document . getElementById ( 'bodyJSON' ) ;
43+ const headersContainerEl = document . getElementById ( 'headers-container' ) ;
44+ const addHeaderBtn = document . getElementById ( 'add-header' ) ;
45+ debugger ;
46+ // Initialize headers with one empty pair
47+ addHeaderField ( ) ;
48+
49+ addHeaderBtn . addEventListener ( 'click' , addHeaderField ) ;
50+
51+ function addHeaderField ( ) {
52+ const headerDiv = document . createElement ( 'div' ) ;
53+ headerDiv . className = 'header-row' ;
54+
55+ const keyInput = document . createElement ( 'input' ) ;
56+ keyInput . type = 'text' ;
57+ keyInput . placeholder = 'Header Name (e.g., Content-Type)' ;
58+
59+ const valueInput = document . createElement ( 'input' ) ;
60+ valueInput . type = 'text' ;
61+ valueInput . placeholder = 'Header Value (e.g., application/json)' ;
62+
63+ const removeBtn = document . createElement ( 'button' ) ;
64+ removeBtn . textContent = 'X' ;
65+ removeBtn . type = 'button' ;
66+ removeBtn . onclick = ( ) => headersContainerEl . removeChild ( headerDiv ) ;
67+
68+ headerDiv . appendChild ( keyInput ) ;
69+ headerDiv . appendChild ( valueInput ) ;
70+ headerDiv . appendChild ( removeBtn ) ;
71+
72+ headersContainerEl . appendChild ( headerDiv ) ;
73+ }
74+
75+ function buildRequestObject ( ) {
76+ const headers = { } ;
77+ const headerRows = headersContainerEl . querySelectorAll ( '.header-row' ) ;
78+
79+ headerRows . forEach ( row => {
80+ const inputs = row . querySelectorAll ( 'input' ) ;
81+ const key = inputs [ 0 ] . value . trim ( ) ;
82+ const val = inputs [ 1 ] . value . trim ( ) ;
83+ if ( key && val ) {
84+ headers [ key ] = val ;
85+ }
86+ } ) ;
87+
88+ let bodyContent ;
89+ try {
90+ bodyContent = bodyEl . value ? JSON . parse ( bodyEl . value ) : null ;
91+ debugger ;
92+ } catch ( e ) {
93+ alert ( 'Invalid JSON in body' ) ;
94+ return ;
95+ }
96+
97+ const requestObject = {
98+ method : methodEl . value ,
99+ uri : urlEl . value ,
100+ headersIn : headers ,
101+ body : bodyContent
102+ } ;
103+
104+ return requestObject ;
19105 }
20- const exampleRequestCode = await exampleResponse . text ( ) ;
106+
107+ //
21108
22109 const exampleNJSResponse = await fetch ( "/njs/{{ .exampleNJS }}" ) ;
23- if ( ! exampleResponse . ok ) {
110+ if ( ! exampleNJSResponse . ok ) {
24111 throw new Error ( `Failed to fetch {{ .exampleRequest }}: ${ exampleNJSResponse . status } ` ) ;
25112 }
26113 const exampleNJSCode = await exampleNJSResponse . text ( ) ;
27114
28- const fnCaller = `
29- const requestConverter = (request) => {
30- return {
31- ...request,
32- requestText: request.body,
33- return: (status, value) => (JSON.stringify({status, value})),
34- }
35- }
36- {{ .fnName }}(requestConverter(exampleRequest))
37- ` ;
115+
38116
39117 ( async ( ) => {
40118 const QuickJS = await getQuickJS ( ) ;
@@ -47,28 +125,38 @@ <h3>NJS Function</h3>
47125 editor = monaco . editor . create ( document . getElementById ( "editor" ) , {
48126 value : exampleNJSCode ,
49127 language : "javascript" ,
50- theme
51- } ) ;
52-
53- requestBuilder = monaco . editor . create ( document . getElementById ( "request-builder" ) , {
54- value : exampleRequestCode ,
55- language : "javascript" ,
56- theme
128+ theme,
129+ minimap : {
130+ enabled : false
131+ }
57132 } ) ;
58133 } ) ;
59134
60135
61-
62136 const runCode = async ( ) => {
63137 const vm = QuickJS . newContext ( ) ;
64138
65139 if ( ! vm ) {
66140 alert ( "QuickJS is loading, please wait a moment." ) ;
67141 return ;
68142 }
69- const requestSrc = requestBuilder . getValue ( ) ;
143+
70144 const src = editor . getValue ( ) ;
71- const result = vm . evalCode ( requestSrc + src + fnCaller ) ;
145+ const requestObject = buildRequestObject ( ) ;
146+ const fnCaller = `
147+ const exampleRequest = ${ JSON . stringify ( requestObject ) } ;
148+ const requestConverter = (request) => {
149+ return {
150+ ...request,
151+ requestText: request.body,
152+ return: (status, value) => (JSON.stringify({status, value})),
153+ }
154+ }
155+ {{ .fnName }}(requestConverter(exampleRequest))
156+ ` ;
157+
158+
159+ const result = vm . evalCode ( src + fnCaller ) ;
72160 const resultEl = document . getElementById ( "result" ) ;
73161
74162 if ( result . error ) {
0 commit comments