@deepkit/api-console-gui
Version:
API Console GUI
354 lines (345 loc) • 15.1 kB
JavaScript
var HttpRouteDetailComponent_1;
import { __decorate } from "tslib";
import { Component, effect, EventEmitter, input, Output } from '@angular/core';
import { isArray, isObject } from '@deepkit/core';
import { extractDataStructure, extractDataStructureFromSchema, Request } from '../../store';
import { ButtonComponent, ButtonGroupComponent, OptionDirective, SelectBoxComponent, TabButtonComponent } from '@deepkit/desktop-ui';
import { headerStatusCodes, methods, typeToTSJSONInterface } from '../../utils';
import { getTypeJitContainer } from '@deepkit/type';
import { FormsModule } from '@angular/forms';
import { CodeHighlightComponent, DeepkitBoxComponent, ToggleBoxComponent } from '@deepkit/ui-library';
import { InputComponent } from '../../components/inputs/input.component';
import { HeadersComponent } from '../../components/headers.component';
let HttpRouteDetailComponent = HttpRouteDetailComponent_1 = class HttpRouteDetailComponent {
constructor(client, store, cd, dialog, router) {
this.client = client;
this.store = store;
this.cd = cd;
this.dialog = dialog;
this.router = router;
this.typeToTSJSONInterface = typeToTSJSONInterface;
this.headerStatusCodes = headerStatusCodes;
this.methods = methods;
this.routeTab = 'query';
this.route = input.required();
this.routeState = input.required();
this.executed = new EventEmitter();
this.codeGenerated = '';
this.codeGenerators = {
'curl': (r, s) => {
const args = [];
for (const h of s.fullHeaders) {
if (!h.name)
continue;
args.push(`-H '${h.name}: ${h.value}'`);
}
if (s.resolvedBody) {
args.push(`-H 'Content-Type: application/json'`);
args.push(`-d '${JSON.stringify(s.resolvedBody)}'`);
}
if (s.method === 'GET')
return `curl ${args.join(' ')} '${s.fullUrl}'`;
return `curl -X ${s.method} ${args.join(' ')} '${s.fullUrl}'`;
},
'http': (r, s) => {
const headers = [];
for (const h of s.fullHeaders) {
if (!h.name)
continue;
headers.push(`${h.name}: ${h.value}`);
}
let body = '';
if (s.resolvedBody) {
body = JSON.stringify(s.resolvedBody);
}
return `${s.method} ${s.fullUrl}${headers.length ? '\n' : ''}${headers.join('\n')}\n\n${body}`;
},
};
effect(() => this.updateRouteState());
}
consoleInputKeyDown(event, route) {
if (event.key.toLowerCase() === 'enter') {
void this.execute(route);
}
}
toggleCodeGenerationVisibility() {
this.store.set(state => {
state.viewHttp.codeGenerationVisible = !state.viewHttp.codeGenerationVisible;
});
}
updateRouteState(route) {
var _a;
route = route || this.store.state.route;
if (!route)
return;
const routeState = this.store.state.routeStates[route.id];
const environment = this.store.state.activeEnvironment;
if (!routeState)
return;
let url = route.path;
const query = [];
function extract(name, value) {
if (value === undefined || value === '')
return;
if (isObject(value)) {
for (const [k, v] of Object.entries(value)) {
extract(name + '[' + k + ']', v);
}
}
else if (isArray(value)) {
for (const v of value) {
extract(name + '[]', v);
}
}
else {
query.push(`${name}=${encodeURIComponent(value)}`);
}
}
const querySchema = route.getQueryType();
if (querySchema) {
const queryData = {};
Object.assign(queryData, extractDataStructureFromSchema(routeState.params, querySchema));
for (const [name, value] of Object.entries(queryData)) {
extract(name, value);
}
}
const urlSchema = route.getUrlType();
if (urlSchema) {
for (const property of urlSchema.getProperties()) {
const regexp = (_a = getTypeJitContainer(property.property))['.deepkit/api-console/url-regex'] || (_a['.deepkit/api-console/url-regex'] = new RegExp(`(:${String(property.name)})([^\w]|$)`));
const v = extractDataStructure(routeState.urls.getProperty(property.name), property.type);
url = url.replace(regexp, function (a, b, c) {
return String(v) + c;
});
}
}
if (query.length) {
if (url.includes('?')) {
url += '&' + query.join('&');
}
else {
url += '?' + query.join('&');
}
}
const bodySchema = route.getBodyType();
if (bodySchema) {
routeState.resolvedBody = extractDataStructureFromSchema(routeState.body, bodySchema);
}
if (environment) {
routeState.fullHeaders = [...environment.headers, ...routeState.headers];
}
else {
routeState.fullHeaders = [...routeState.headers];
}
routeState.fullUrl = HttpRouteDetailComponent_1.getUrl() + url;
this.codeGenerated = this.codeGenerators[this.store.state.viewHttp.codeGenerationType]?.(route, routeState) || '';
this.store.store();
}
static getUrl() {
return location.protocol + '//' + (location.port === '4200' ? location.hostname + ':8080' : location.host);
}
async execute(route) {
route = route || this.store.state.route;
if (!route)
return;
const routeState = this.store.state.routeStates[route.id];
if (!routeState)
return;
this.updateRouteState(route);
const request = new Request(routeState.id, routeState.method, routeState.fullUrl);
this.store.set(state => {
if (state.requests.length && state.requests[state.requests.length - 1].open === undefined) {
state.requests[state.requests.length - 1].open = false;
}
state.requests.unshift(request);
if (state.requests.length > 100)
state.requests.splice(100);
});
// this.updateRequests();
try {
const start = performance.now();
let body = undefined;
const headers = {};
for (const { name, value } of routeState.fullHeaders) {
headers[name] = value;
}
if (routeState.resolvedBody) {
body = JSON.stringify(routeState.resolvedBody);
headers['Content-Type'] = 'application/json';
}
this.cd.detectChanges();
const response = await fetch(routeState.fullUrl, { method: routeState.method, body, headers });
request.took = performance.now() - start;
request.status = response.status;
request.statusText = response.statusText;
for (const [name, value] of response.headers) {
request.headers.push({ name, value });
}
this.cd.detectChanges();
const result = await response.text();
const contentType = response.headers.get('content-type') || '';
if (contentType.startsWith('application/json')) {
request.json = JSON.stringify(JSON.parse(result), undefined, 4);
}
else {
request.result = result;
}
this.cd.detectChanges();
}
catch (error) {
request.error = error.message;
}
this.executed.emit();
this.store.store();
this.cd.detectChanges();
}
};
__decorate([
Output()
], HttpRouteDetailComponent.prototype, "executed", void 0);
HttpRouteDetailComponent = HttpRouteDetailComponent_1 = __decorate([
Component({
selector: 'api-console-route-detail',
template: `
<div class="route">
<div class="url-input-container">
<dui-button-group padding="none">
<dui-select style="width: 85px;" [(ngModel)]="routeState().method" textured>
(m of methods; track $index) {
<dui-option
[value]="m"
[disabled]="!route().httpMethods.includes(m)">{{ m }}
</dui-option>
}
</dui-select>
<div class="url text-selection">
<div>{{ route().path }}</div>
</div>
<dui-button icon="play" textured (click)="execute(route())"></dui-button>
</dui-button-group>
</div>
<div class="route-container overlay-scrollbar-small">
<dui-button-group style="margin: 6px 1px;">
<dui-tab-button (click)="routeTab = 'query'" [active]="routeTab === 'query'">Query</dui-tab-button>
<dui-tab-button (click)="routeTab = 'body'" [active]="routeTab === 'body'">Body</dui-tab-button>
<dui-tab-button (click)="routeTab = 'header'" [active]="routeTab === 'header'">Header</dui-tab-button>
</dui-button-group>
(routeTab === 'body') {
<deepkit-box>
(!route().getBodyType()) {
<div class="box-info-text">This route has no body defined.</div>
}
(route().getBodyType(); as schema) {
(p of schema.getProperties(); track $index) {
<api-console-input [decoration]="p" (keyDown)="consoleInputKeyDown($event, route())"
[model]="routeState().body.getProperty(p.name)"
[type]="p.property"
(modelChange)="updateRouteState(route())"></api-console-input>
}
<div class="ts text-selection">
<code-highlight [code]="typeToTSJSONInterface(schema.type, {defaultIsOptional: true})"></code-highlight>
</div>
}
</deepkit-box>
}
(routeTab === 'header') {
<deepkit-box style="padding: 0">
<api-console-headers [(model)]="routeState().headers" (modelChange)="updateRouteState(route())"></api-console-headers>
</deepkit-box>
}
(routeTab === 'query') {
<deepkit-box style="padding-top: 0;">
(!route().getQueryType() && !route().getUrlType()) {
<div class="box-info-text">This route has no query parameters defined.</div>
}
(route().getUrlType(); as schema) {
(p of schema.getProperties(); track $index) {
<api-console-input [decoration]="p" (keyDown)="consoleInputKeyDown($event, route())"
[model]="routeState().urls.getProperty(p.name)"
[type]="p.property"
(modelChange)="updateRouteState(route())"></api-console-input>
}
}
(route().getQueryType(); as schema) {
(p of schema.getProperties(); track $index) {
<api-console-input [decoration]="p" (keyDown)="consoleInputKeyDown($event, route())"
[model]="routeState().params.getProperty(p.name)"
[type]="p.property"
(modelChange)="updateRouteState(route())"></api-console-input>
}
<div class="ts text-selection">
<code-highlight [code]="typeToTSJSONInterface(schema.type, {defaultIsOptional: true})"></code-highlight>
</div>
}
</deepkit-box>
}
<deepkit-box style="padding: 12px">
<div class="labeled-values">
<div>
<label>Category</label>
{{ route().category || 'none' }}
</div>
<div>
<label>Groups</label>
{{ route().groups.join(',') || 'none' }}
</div>
<div style="margin-top: 10px; flex: 2 1 auto;">
<label>Description</label>
<div class="formatted-text">{{ route().description || 'none' }}</div>
</div>
</div>
</deepkit-box>
(!route().responses.length) {
(route().getResultType(); as schema) {
<deepkit-box title="Default response">
<div class="ts text-selection">
<code-highlight [code]="typeToTSJSONInterface(schema)"></code-highlight>
</div>
</deepkit-box>
}
}
(response of route().responses; track $index) {
<deepkit-box title="Response {{response.statusCode}} {{headerStatusCodes[response.statusCode + '']}}"
>
<div class="response-description">
{{ response.description }}
</div>
(response.getType(); as s) {
<div class="ts text-selection">
<code-highlight [code]="typeToTSJSONInterface(s)"></code-highlight>
</div>
}
</deepkit-box>
}
</div>
</div>
<deepkit-toggle-box title="Code-generation" [(visible)]="store.state.viewHttp.codeGenerationVisible" (visibleChange)="store.store()">
<ng-container header>
<dui-select textured small [(ngModel)]="store.state.viewHttp.codeGenerationType" (ngModelChange)="updateRouteState(route())">
<dui-option value="curl">cURL</dui-option>
<dui-option value="http">HTTP</dui-option>
</dui-select>
</ng-container>
(store.state.viewHttp.codeGenerationVisible) {
<code-highlight class="code-generation-code" inline lang="bash" [code]="codeGenerated"></code-highlight>
}
</deepkit-toggle-box>
`,
styleUrls: ['./route-detail.component.scss'],
imports: [
ButtonGroupComponent,
SelectBoxComponent,
OptionDirective,
FormsModule,
ButtonComponent,
TabButtonComponent,
DeepkitBoxComponent,
InputComponent,
CodeHighlightComponent,
HeadersComponent,
ToggleBoxComponent,
],
})
], HttpRouteDetailComponent);
export { HttpRouteDetailComponent };
//# sourceMappingURL=route-detail.component.js.map