mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-20 16:01:18 +02:00
Base environments fully working
This commit is contained in:
@@ -93,8 +93,11 @@ async fn actually_send_ephemeral_request(
|
|||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
let environment = models::get_environment(environment_id, pool).await.ok();
|
let environment = models::get_environment(environment_id, pool).await.ok();
|
||||||
let environment_ref = environment.as_ref();
|
let environment_ref = environment.as_ref();
|
||||||
|
let workspace = models::get_workspace(&request.workspace_id, pool)
|
||||||
|
.await
|
||||||
|
.expect("Failed to get workspace");
|
||||||
|
|
||||||
let mut url_string = render::render(&request.url, environment.as_ref());
|
let mut url_string = render::render(&request.url, &workspace, environment.as_ref());
|
||||||
|
|
||||||
if !url_string.starts_with("http://") && !url_string.starts_with("https://") {
|
if !url_string.starts_with("http://") && !url_string.starts_with("https://") {
|
||||||
url_string = format!("http://{}", url_string);
|
url_string = format!("http://{}", url_string);
|
||||||
@@ -119,8 +122,8 @@ async fn actually_send_ephemeral_request(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = render::render(&h.name, environment_ref);
|
let name = render::render(&h.name, &workspace, environment_ref);
|
||||||
let value = render::render(&h.value, environment_ref);
|
let value = render::render(&h.value, &workspace, environment_ref);
|
||||||
|
|
||||||
let header_name = match HeaderName::from_bytes(name.as_bytes()) {
|
let header_name = match HeaderName::from_bytes(name.as_bytes()) {
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
@@ -155,8 +158,8 @@ async fn actually_send_ephemeral_request(
|
|||||||
.unwrap_or(empty_value)
|
.unwrap_or(empty_value)
|
||||||
.as_str()
|
.as_str()
|
||||||
.unwrap_or("");
|
.unwrap_or("");
|
||||||
let username = render::render(raw_username, environment_ref);
|
let username = render::render(raw_username, &workspace, environment_ref);
|
||||||
let password = render::render(raw_password, environment_ref);
|
let password = render::render(raw_password, &workspace, environment_ref);
|
||||||
|
|
||||||
let auth = format!("{username}:{password}");
|
let auth = format!("{username}:{password}");
|
||||||
let encoded = base64::engine::general_purpose::STANDARD_NO_PAD.encode(auth);
|
let encoded = base64::engine::general_purpose::STANDARD_NO_PAD.encode(auth);
|
||||||
@@ -166,7 +169,7 @@ async fn actually_send_ephemeral_request(
|
|||||||
);
|
);
|
||||||
} else if b == "bearer" {
|
} else if b == "bearer" {
|
||||||
let raw_token = a.get("token").unwrap_or(empty_value).as_str().unwrap_or("");
|
let raw_token = a.get("token").unwrap_or(empty_value).as_str().unwrap_or("");
|
||||||
let token = render::render(raw_token, environment_ref);
|
let token = render::render(raw_token, &workspace, environment_ref);
|
||||||
headers.insert(
|
headers.insert(
|
||||||
"Authorization",
|
"Authorization",
|
||||||
HeaderValue::from_str(&format!("Bearer {token}")).unwrap(),
|
HeaderValue::from_str(&format!("Bearer {token}")).unwrap(),
|
||||||
@@ -180,7 +183,7 @@ async fn actually_send_ephemeral_request(
|
|||||||
|
|
||||||
let sendable_req_result = match (request.body, request.body_type) {
|
let sendable_req_result = match (request.body, request.body_type) {
|
||||||
(Some(raw_body), Some(_)) => {
|
(Some(raw_body), Some(_)) => {
|
||||||
let body = render::render(&raw_body, environment_ref);
|
let body = render::render(&raw_body, &workspace, environment_ref);
|
||||||
builder.body(body).build()
|
builder.body(body).build()
|
||||||
}
|
}
|
||||||
_ => builder.build(),
|
_ => builder.build(),
|
||||||
|
|||||||
@@ -1,24 +1,27 @@
|
|||||||
use crate::models::Environment;
|
use crate::models::{Environment, Workspace};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tauri::regex::Regex;
|
use tauri::regex::Regex;
|
||||||
|
|
||||||
pub fn render(template: &str, environment: Option<&Environment>) -> String {
|
pub fn render(template: &str, workspace: &Workspace, environment: Option<&Environment>) -> String {
|
||||||
match environment {
|
|
||||||
Some(environment) => render_with_environment(template, environment),
|
|
||||||
None => template.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_with_environment(template: &str, environment: &Environment) -> String {
|
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
let variables = &environment.variables.0;
|
let workspace_variables = &workspace.variables.0;
|
||||||
for variable in variables {
|
for variable in workspace_variables {
|
||||||
if !variable.enabled {
|
if !variable.enabled || variable.value.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
map.insert(variable.name.as_str(), variable.value.as_str());
|
map.insert(variable.name.as_str(), variable.value.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(e) = environment {
|
||||||
|
let environment_variables = &e.variables.0;
|
||||||
|
for variable in environment_variables {
|
||||||
|
if !variable.enabled || variable.value.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
map.insert(variable.name.as_str(), variable.value.as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Regex::new(r"\$\{\[\s*([^]\s]+)\s*]}")
|
Regex::new(r"\$\{\[\s*([^]\s]+)\s*]}")
|
||||||
.expect("Failed to create regex")
|
.expect("Failed to create regex")
|
||||||
.replace_all(template, |caps: &tauri::regex::Captures| {
|
.replace_all(template, |caps: &tauri::regex::Captures| {
|
||||||
|
|||||||
@@ -52,7 +52,11 @@ export const EnvironmentActionsDropdown = memo(function EnvironmentActionsDropdo
|
|||||||
label: e.name,
|
label: e.name,
|
||||||
rightSlot: e.id === activeEnvironment?.id ? <Icon icon="check" /> : undefined,
|
rightSlot: e.id === activeEnvironment?.id ? <Icon icon="check" /> : undefined,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
routes.setEnvironment(e);
|
if (e.id !== activeEnvironment?.id) {
|
||||||
|
routes.setEnvironment(e);
|
||||||
|
} else {
|
||||||
|
routes.setEnvironment(null);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[activeEnvironment?.id],
|
[activeEnvironment?.id],
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export const EnvironmentEditDialog = function ({ initialEnvironment }: Props) {
|
|||||||
justify="start"
|
justify="start"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'w-full',
|
'w-full',
|
||||||
'text-gray-600 hocus:text-gray-800',
|
'text-gray-600 hocus:text-gray-800 !ring-0',
|
||||||
selectedEnvironment == null && 'bg-highlightSecondary !text-gray-900',
|
selectedEnvironment == null && 'bg-highlightSecondary !text-gray-900',
|
||||||
)}
|
)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export function Overlay({
|
|||||||
return (
|
return (
|
||||||
<Portal name={portalName}>
|
<Portal name={portalName}>
|
||||||
{open && (
|
{open && (
|
||||||
<FocusTrap>
|
<FocusTrap>
|
||||||
<motion.div
|
<motion.div
|
||||||
className={classNames('fixed inset-0', zIndexes[zIndex])}
|
className={classNames('fixed inset-0', zIndexes[zIndex])}
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { baseExtensions, getLanguageExtension, multiLineExtensions } from './ext
|
|||||||
import type { GenericCompletionConfig } from './genericCompletion';
|
import type { GenericCompletionConfig } from './genericCompletion';
|
||||||
import { singleLineExt } from './singleLine';
|
import { singleLineExt } from './singleLine';
|
||||||
import { useActiveEnvironment } from '../../../hooks/useActiveEnvironment';
|
import { useActiveEnvironment } from '../../../hooks/useActiveEnvironment';
|
||||||
|
import { useActiveWorkspace } from '../../../hooks/useActiveWorkspace';
|
||||||
|
|
||||||
// Export some things so all the code-split parts are in this file
|
// Export some things so all the code-split parts are in this file
|
||||||
export { buildClientSchema, getIntrospectionQuery } from 'graphql/utilities';
|
export { buildClientSchema, getIntrospectionQuery } from 'graphql/utilities';
|
||||||
@@ -72,7 +73,9 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
|
|||||||
ref,
|
ref,
|
||||||
) {
|
) {
|
||||||
const e = useActiveEnvironment();
|
const e = useActiveEnvironment();
|
||||||
|
const w = useActiveWorkspace();
|
||||||
const environment = autocompleteVariables ? e : null;
|
const environment = autocompleteVariables ? e : null;
|
||||||
|
const workspace = autocompleteVariables ? w : null;
|
||||||
|
|
||||||
const cm = useRef<{ view: EditorView; languageCompartment: Compartment } | null>(null);
|
const cm = useRef<{ view: EditorView; languageCompartment: Compartment } | null>(null);
|
||||||
useImperativeHandle(ref, () => cm.current?.view);
|
useImperativeHandle(ref, () => cm.current?.view);
|
||||||
@@ -124,9 +127,15 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cm.current === null) return;
|
if (cm.current === null) return;
|
||||||
const { view, languageCompartment } = cm.current;
|
const { view, languageCompartment } = cm.current;
|
||||||
const ext = getLanguageExtension({ contentType, environment, useTemplating, autocomplete });
|
const ext = getLanguageExtension({
|
||||||
|
contentType,
|
||||||
|
environment,
|
||||||
|
workspace,
|
||||||
|
useTemplating,
|
||||||
|
autocomplete,
|
||||||
|
});
|
||||||
view.dispatch({ effects: languageCompartment.reconfigure(ext) });
|
view.dispatch({ effects: languageCompartment.reconfigure(ext) });
|
||||||
}, [contentType, autocomplete, useTemplating, environment]);
|
}, [contentType, autocomplete, useTemplating, environment, workspace]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cm.current === null) return;
|
if (cm.current === null) return;
|
||||||
@@ -152,6 +161,7 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
|
|||||||
useTemplating,
|
useTemplating,
|
||||||
autocomplete,
|
autocomplete,
|
||||||
environment,
|
environment,
|
||||||
|
workspace,
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = EditorState.create({
|
const state = EditorState.create({
|
||||||
@@ -271,7 +281,7 @@ function getExtensions({
|
|||||||
EditorView.domEventHandlers({
|
EditorView.domEventHandlers({
|
||||||
focus: () => onFocus.current?.(),
|
focus: () => onFocus.current?.(),
|
||||||
blur: () => onBlur.current?.(),
|
blur: () => onBlur.current?.(),
|
||||||
keydown: e => onKeyDown.current?.(e),
|
keydown: (e) => onKeyDown.current?.(e),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Handle onChange
|
// Handle onChange
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import type { EditorProps } from './index';
|
|||||||
import { text } from './text/extension';
|
import { text } from './text/extension';
|
||||||
import { twig } from './twig/extension';
|
import { twig } from './twig/extension';
|
||||||
import { url } from './url/extension';
|
import { url } from './url/extension';
|
||||||
import type { Environment } from '../../../lib/models';
|
import type { Environment, Workspace } from '../../../lib/models';
|
||||||
|
|
||||||
export const myHighlightStyle = HighlightStyle.define([
|
export const myHighlightStyle = HighlightStyle.define([
|
||||||
{
|
{
|
||||||
@@ -96,8 +96,9 @@ export function getLanguageExtension({
|
|||||||
contentType,
|
contentType,
|
||||||
useTemplating = false,
|
useTemplating = false,
|
||||||
environment,
|
environment,
|
||||||
|
workspace,
|
||||||
autocomplete,
|
autocomplete,
|
||||||
}: { environment: Environment | null } & Pick<
|
}: { environment: Environment | null; workspace: Workspace | null } & Pick<
|
||||||
EditorProps,
|
EditorProps,
|
||||||
'contentType' | 'useTemplating' | 'autocomplete'
|
'contentType' | 'useTemplating' | 'autocomplete'
|
||||||
>) {
|
>) {
|
||||||
@@ -110,7 +111,7 @@ export function getLanguageExtension({
|
|||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
return twig(base, environment, autocomplete);
|
return twig(base, environment, workspace, autocomplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const baseExtensions = [
|
export const baseExtensions = [
|
||||||
|
|||||||
@@ -7,14 +7,17 @@ import { placeholders } from './placeholder';
|
|||||||
import { textLanguageName } from '../text/extension';
|
import { textLanguageName } from '../text/extension';
|
||||||
import { twigCompletion } from './completion';
|
import { twigCompletion } from './completion';
|
||||||
import { parser as twigParser } from './twig';
|
import { parser as twigParser } from './twig';
|
||||||
import type { Environment } from '../../../../lib/models';
|
import type { Environment, Workspace } from '../../../../lib/models';
|
||||||
|
|
||||||
export function twig(
|
export function twig(
|
||||||
base: LanguageSupport,
|
base: LanguageSupport,
|
||||||
environment: Environment | null,
|
environment: Environment | null,
|
||||||
|
workspace: Workspace | null,
|
||||||
autocomplete?: GenericCompletionConfig,
|
autocomplete?: GenericCompletionConfig,
|
||||||
) {
|
) {
|
||||||
const variables = environment?.variables.filter(v => v.enabled) ?? [];
|
const variables =
|
||||||
|
[...(workspace?.variables ?? []), ...(environment?.variables ?? [])].filter((v) => v.enabled) ??
|
||||||
|
[];
|
||||||
const completions = twigCompletion({ options: variables });
|
const completions = twigCompletion({ options: variables });
|
||||||
|
|
||||||
const language = mixLanguage(base);
|
const language = mixLanguage(base);
|
||||||
|
|||||||
@@ -53,18 +53,18 @@ export function useAppRoutes() {
|
|||||||
}, [nav]);
|
}, [nav]);
|
||||||
|
|
||||||
const setEnvironment = useCallback(
|
const setEnvironment = useCallback(
|
||||||
({ id: environmentId }: Environment) => {
|
(environment: Environment | null) => {
|
||||||
if (workspaceId == null) {
|
if (workspaceId == null) {
|
||||||
navigate('workspaces');
|
navigate('workspaces');
|
||||||
} else if (requestId == null) {
|
} else if (requestId == null) {
|
||||||
navigate('workspace', {
|
navigate('workspace', {
|
||||||
workspaceId: workspaceId,
|
workspaceId: workspaceId,
|
||||||
environmentId: environmentId ?? null,
|
environmentId: environment == null ? undefined : environment.id,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
navigate('request', {
|
navigate('request', {
|
||||||
workspaceId,
|
workspaceId,
|
||||||
environmentId: environmentId ?? null,
|
environmentId: environment == null ? undefined : environment.id,
|
||||||
requestId,
|
requestId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user