groqd-playground
Version:
Groqd Playground is a plugin for Sanity Studio for testing [groqd](https://formidable.com/open-source/groqd/) queries, featuring:
759 lines (735 loc) • 28.2 kB
JavaScript
import {
__async,
__spreadProps,
__spreadValues
} from "./chunk-JXPB73SY.mjs";
// src/PlaygroundWrapper.tsx
import * as React6 from "react";
import { ToastProvider } from "@sanity/ui";
// src/components/Playground.tsx
import * as React5 from "react";
import { useClient } from "sanity";
import {
Box as Box5,
Button as Button3,
Card as Card2,
Code,
Flex as Flex2,
Grid,
Label as Label3,
Select,
Spinner,
Stack as Stack4,
Text as Text2,
Tooltip as Tooltip2
} from "@sanity/ui";
import { z } from "zod";
import * as q from "groqd";
import has from "lodash.has";
import Split from "@uiw/react-split";
import { PlayIcon, ResetIcon } from "@sanity/icons";
// src/util/useDatasets.ts
import * as React from "react";
var useDatasets = (client) => {
const [datasets, setDatasets] = React.useState([]);
React.useEffect(() => {
const datasets$ = client.observable.datasets.list().subscribe({
next: (result) => setDatasets(result.map((ds) => ds.name))
});
return () => datasets$.unsubscribe();
}, []);
return datasets;
};
// src/consts.ts
var STORAGE_KEYS = {
DATASET: "__groqd_playground_dataset",
API_VERSION: "__groqd_playground_api_version",
CODE: "__groqd_playground_code",
EDITOR_WIDTH: "__groqd_playground_editor_width"
};
var API_VERSIONS = ["v1", "vX", "v2021-03-25", "v2021-10-21"];
var DEFAULT_API_VERSION = API_VERSIONS.at(-1);
// src/components/ShareUrlField.tsx
import * as React3 from "react";
import {
Box,
Button,
Card,
Flex,
Label,
Stack,
Text,
TextInput,
Tooltip
} from "@sanity/ui";
import { CopyIcon } from "@sanity/icons";
// src/util/copyDataToClipboard.ts
import * as React2 from "react";
import { useToast } from "@sanity/ui";
var useCopyDataAndNotify = (message) => {
const toast = useToast();
return React2.useCallback(
(url2) => {
navigator.clipboard.writeText(url2).then(() => {
toast.push({ title: message });
});
},
[message]
);
};
// src/components/ShareUrlField.tsx
var ShareUrlField = ({
title,
url: url2,
column = 4,
notificationMessage = "Copied URL to clipboard!"
}) => {
const copyUrl = useCopyDataAndNotify(notificationMessage);
const handleCopyUrl = () => copyUrl(url2);
return /* @__PURE__ */ React3.createElement(Box, { padding: 1, flex: 1, column }, /* @__PURE__ */ React3.createElement(Stack, null, /* @__PURE__ */ React3.createElement(Card, { paddingY: 2 }, /* @__PURE__ */ React3.createElement(Label, { muted: true }, title)), /* @__PURE__ */ React3.createElement(Flex, { flex: 1, gap: 1 }, /* @__PURE__ */ React3.createElement(Box, { flex: 1 }, /* @__PURE__ */ React3.createElement(TextInput, { readOnly: true, type: "url", value: url2 })), /* @__PURE__ */ React3.createElement(
Tooltip,
{
content: /* @__PURE__ */ React3.createElement(Box, { padding: 2 }, /* @__PURE__ */ React3.createElement(Text, null, "Copy to clipboard"))
},
/* @__PURE__ */ React3.createElement(
Button,
{
"aria-label": "Copy to clipboard",
type: "button",
mode: "ghost",
icon: CopyIcon,
onClick: handleCopyUrl
}
)
))));
};
// src/util/messaging.ts
var emitReset = (iframe, target) => {
var _a2;
(_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage(
JSON.stringify({ event: "RESET_CODE" }),
target
);
};
var emitInit = (source, target, payload) => {
source.postMessage(JSON.stringify(__spreadValues({ event: "INIT" }, payload)), {
targetOrigin: target
});
};
// src/components/JSONExplorer.tsx
import * as React4 from "react";
import { Box as Box3, Button as Button2, Stack as Stack3 } from "@sanity/ui";
// src/components/JSONExplorer.styled.tsx
import styled from "styled-components";
import { Box as Box2, Stack as Stack2 } from "@sanity/ui";
var Root = styled(Box2)`
font-family: Menlo, monospace;
font-size: 0.9em;
position: relative;
height: 100%;
--border-radius: 4px;
--error-bg-color: #ffe5ea;
--item-hover-color: #e7e7e7;
@media (prefers-color-scheme: dark) {
--error-bg-color: #470417;
--item-hover-color: #505050;
}
`;
var Label2 = styled.span`
color: #9d1fcd;
@media (prefers-color-scheme: dark) {
color: #d05afc;
}
`;
var Key = styled.span`
color: #1e61cd;
@media (prefers-color-scheme: dark) {
color: #5998fc;
}
`;
var Value = styled.span`
color: #967e1c;
@media (prefers-color-scheme: dark) {
color: #dbb931;
}
`;
var LineItem = styled(Box2)`
padding-left: ${({ depth }) => depth * DEPTH_SC}px;
border-radius: var(--border-radius);
cursor: ${({ pointer }) => pointer ? "pointer" : "initial"};
background-color: ${({ hasError }) => hasError ? "var(--error-bg-color)" : "initial"};
&:hover {
background-color: ${({ hasError }) => hasError ? void 0 : "var(--item-hover-color)"};
}
`;
var CollapsibleContainer = styled(Stack2)`
border-radius: var(--border-radius);
background-color: ${({ hasError }) => hasError ? "var(--error-bg-color)" : "initial"};
`;
var ErrorMessageText = styled.div`
font-weight: 400;
`;
var DEPTH_SC = 15;
// src/components/JSONExplorer.tsx
import { CopyIcon as CopyIcon2 } from "@sanity/icons";
// ../../shared/util/jsonExplorerUtils.ts
var formatPrimitiveData = (data) => {
if (typeof data === "string")
return `"${data}"`;
if (data instanceof Date)
return `(Date) ${data}`;
return String(data);
};
var isObject = (data) => typeof data === "object" && data !== null && !Array.isArray(data) && !(data instanceof Date);
var addToPath = (existingPath, newSegment) => existingPath ? `${existingPath}.${newSegment}` : newSegment;
// src/components/JSONExplorer.tsx
var JSONExplorer = (props) => {
const copyUrl = useCopyDataAndNotify("Copied JSON to clipboard!");
const handleCopy = () => {
try {
copyUrl(JSON.stringify(props.data, null, 2));
} catch (e) {
}
};
return /* @__PURE__ */ React4.createElement(Root, { flex: 1 }, /* @__PURE__ */ React4.createElement(
Box3,
{
padding: 3,
style: { position: "absolute", inset: 0 },
overflow: "auto"
},
/* @__PURE__ */ React4.createElement(JSONExplorerDisplay, __spreadValues({}, props))
), /* @__PURE__ */ React4.createElement(Box3, { style: { position: "absolute", bottom: 0, right: 0 }, padding: 3 }, /* @__PURE__ */ React4.createElement(
Button2,
{
"aria-label": "Copy to clipboard",
type: "button",
mode: "ghost",
icon: CopyIcon2,
text: "Copy to clipboard",
onClick: handleCopy
}
)));
};
var JSONExplorerDisplay = ({
data,
prefix,
highlightedPaths,
currentPath = ""
}) => {
const prefixDisplay = prefix !== void 0 ? /* @__PURE__ */ React4.createElement(Key, null, prefix, ": ") : null;
const errorMessage = highlightedPaths && highlightedPaths.get(currentPath);
const depth = currentPath === "" ? 0 : (currentPath == null ? void 0 : currentPath.split(".").length) || 0;
if (Array.isArray(data)) {
return /* @__PURE__ */ React4.createElement(
Collapsible,
{
depth,
title: /* @__PURE__ */ React4.createElement(React4.Fragment, null, prefixDisplay, /* @__PURE__ */ React4.createElement(Label2, null, "[...] ", data.length, " items")),
errorMessage,
id: `json-item-${currentPath}`
},
/* @__PURE__ */ React4.createElement(Stack3, { space: 2 }, data.map((dat, i) => /* @__PURE__ */ React4.createElement(
JSONExplorerDisplay,
{
data: dat,
key: i,
prefix: String(i),
currentPath: addToPath(currentPath, String(i)),
highlightedPaths
}
)))
);
}
if (isObject(data)) {
return /* @__PURE__ */ React4.createElement(
Collapsible,
{
depth,
title: /* @__PURE__ */ React4.createElement(React4.Fragment, null, prefixDisplay, /* @__PURE__ */ React4.createElement(Label2, null, `{...}`, " ", Object.keys(data).length, " properties")),
errorMessage,
id: `json-item-${currentPath}`
},
/* @__PURE__ */ React4.createElement(Stack3, { space: 2 }, Object.entries(data).map(([key, dat]) => /* @__PURE__ */ React4.createElement(
JSONExplorerDisplay,
{
data: dat,
key,
prefix: key,
currentPath: addToPath(currentPath, key),
highlightedPaths
}
)))
);
}
return /* @__PURE__ */ React4.createElement(
LineItem,
{
paddingY: 1,
depth,
hasError: !!errorMessage,
id: `json-item-${currentPath}`
},
/* @__PURE__ */ React4.createElement(Stack3, { space: 1 }, errorMessage && /* @__PURE__ */ React4.createElement(ErrorMessageText, null, errorMessage), /* @__PURE__ */ React4.createElement("div", null, prefixDisplay, /* @__PURE__ */ React4.createElement(Value, null, formatPrimitiveData(data)), " "))
);
};
var Collapsible = ({
title,
depth,
children,
errorMessage,
id
}) => {
const [isExpanded, setIsExpanded] = React4.useState(true);
return /* @__PURE__ */ React4.createElement(CollapsibleContainer, { space: 2, id, hasError: !!errorMessage }, /* @__PURE__ */ React4.createElement(
LineItem,
{
paddingY: 1,
depth,
onClick: () => setIsExpanded((v) => !v),
pointer: true
},
/* @__PURE__ */ React4.createElement(Stack3, { space: 1 }, errorMessage && /* @__PURE__ */ React4.createElement(ErrorMessageText, null, errorMessage), /* @__PURE__ */ React4.createElement(Box3, null, title))
), /* @__PURE__ */ React4.createElement("div", { style: { height: isExpanded ? "auto" : 0, overflow: "hidden" } }, children));
};
// src/components/Playground.styled.tsx
import styled2 from "styled-components";
import { Box as Box4 } from "@sanity/ui";
var ErrorLineItem = styled2(Box4)`
border-radius: 4px;
cursor: pointer;
&:hover {
background-color: #e7e7e7;
}
@media (prefers-color-scheme: dark) {
&:hover {
background-color: #505050;
}
}
`;
var CopyQueryButton = styled2.button`
all: unset;
cursor: pointer;
&:focus {
box-shadow: inset 0 0 0 1px var(--card-border-color), 0 0 0 1px #fff,
0 0 0 3px var(--card-focus-ring-color);
border-radius: 0.1875rem;
}
`;
// ../../shared/util/formatErrorPath.ts
var formatErrorPath = (path) => path.split(".").reduce((acc, el) => {
if (!NumReg.test(el)) {
return `${acc}.${el}`;
}
return `${acc}[${el}]`;
}, "");
var NumReg = /\d+/;
// src/components/Playground.tsx
function GroqdPlayground({ tool }) {
var _a2;
const [
{
query,
params,
parsedResponse,
fetchParseError,
rawResponse,
activeDataset,
activeAPIVersion,
queryUrl,
isFetching,
rawExecutionTime,
errorPaths
},
dispatch
] = React5.useReducer(reducer, null, () => {
var _a3, _b;
const activeDataset2 = localStorage.getItem(STORAGE_KEYS.DATASET) || ((_a3 = tool.options) == null ? void 0 : _a3.defaultDataset) || "production";
const activeAPIVersion2 = localStorage.getItem(STORAGE_KEYS.API_VERSION) || ((_b = tool.options) == null ? void 0 : _b.defaultApiVersion) || DEFAULT_API_VERSION;
return {
query: q.q(""),
activeDataset: activeDataset2,
activeAPIVersion: activeAPIVersion2,
isFetching: false
};
});
const iframeRef = React5.useRef(null);
const editorContainer = React5.useRef(null);
const editorInitialWidth = React5.useMemo(
() => +(localStorage.getItem(STORAGE_KEYS.EDITOR_WIDTH) || 0) || EDITOR_INITIAL_WIDTH,
[]
);
const copyShareUrl = useCopyDataAndNotify("Copied share URL to clipboard!");
const copyQueryUrl = useCopyDataAndNotify("Copied Query to clipboard!");
const windowHref = window.location.href;
const _client = useClient({
apiVersion: ((_a2 = tool.options) == null ? void 0 : _a2.defaultApiVersion) || "v2021-10-21"
});
const client = React5.useMemo(
() => _client.withConfig({
dataset: activeDataset,
apiVersion: activeAPIVersion
}),
[_client, activeDataset, activeAPIVersion]
);
const datasets = useDatasets(_client);
const generateQueryUrl = (query2, params2) => {
const searchParams = new URLSearchParams();
searchParams.append("query", query2.query);
if (params2) {
for (const [key, value] of Object.entries(params2))
searchParams.append(key, String(value));
}
return client.getUrl(
client.getDataUrl("query", "?" + searchParams.toString())
);
};
React5.useEffect(() => {
if (datasets[0] && !datasets.includes(activeDataset))
handleDatasetChange(datasets[0]);
}, [datasets]);
const runQuery = React5.useMemo(
() => q.makeSafeQueryRunner(
(query2, params2) => new Promise((resolve, reject) => {
client.observable.fetch(query2, params2, { filterResponse: false }).subscribe({
next: (res) => {
dispatch({
type: "RAW_RESPONSE_RECEIVED",
payload: { rawResponse: res.result, execTime: res.ms }
});
resolve(res.result);
},
error: (err) => {
reject(err);
}
});
})
),
[client]
);
const handleRun = (query2, params2) => __async(this, null, function* () {
dispatch({
type: "MAKE_FETCH_REQUEST",
payload: { queryUrl: generateQueryUrl(query2, params2) }
});
try {
const data = yield runQuery(query2, params2);
dispatch({
type: "FETCH_RESPONSE_PARSED",
payload: { parsedResponse: data }
});
} catch (err) {
let errorPaths2;
if (err instanceof q.GroqdParseError) {
errorPaths2 = /* @__PURE__ */ new Map();
for (const e of err.zodError.errors) {
if (e.message === "Required" && !has(err.rawResponse, e.path)) {
errorPaths2.set(
e.path.slice(0, -1).map((v) => String(v)).join("."),
`Field "${e.path.at(-1)}" is Required`
);
} else {
errorPaths2.set(e.path.map((v) => String(v)).join("."), e.message);
}
}
}
dispatch({
type: "FETCH_PARSE_FAILURE",
payload: { fetchParseError: err, errorPaths: errorPaths2 }
});
}
});
React5.useEffect(() => {
const handleMessage = (message) => {
if (message.origin !== EDITOR_ORIGIN)
return;
try {
const payload = messageSchema.parse(JSON.parse(message.data));
if (payload.event === "READY") {
const storedCode = new URL(window.location.href).searchParams.get("code") || localStorage.getItem(STORAGE_KEYS.CODE);
message.source && emitInit(message.source, EDITOR_ORIGIN, {
code: storedCode || void 0,
origin: window.location.origin
});
} else if (payload.event === "INPUT") {
localStorage.setItem(STORAGE_KEYS.CODE, payload.compressedRawCode);
setQP("code", payload.compressedRawCode);
if (payload.requestShareCopy) {
copyShareUrl(window.location.href);
}
let playgroundRunQueryCount = 0;
const libs = {
groqd: q,
playground: {
runQuery: (query2, params2) => {
playgroundRunQueryCount++;
if (playgroundRunQueryCount > 1)
return;
try {
if (query2 instanceof q.BaseQuery) {
dispatch({
type: "INPUT_EVAL_SUCCESS",
payload: { query: query2, params: params2 }
});
if (payload.requestImmediateFetch) {
handleRun(query2, params2);
}
}
} catch (e) {
}
}
}
};
const scope = {
exports: {},
require: (name) => libs[name]
};
const keys = Object.keys(scope);
new Function(...keys, payload.code)(
...keys.map((key) => scope[key])
);
} else if (payload.event === "ERROR") {
console.error(payload.message);
}
} catch (e) {
}
};
window.addEventListener("message", handleMessage);
return () => {
window.removeEventListener("message", handleMessage);
};
}, []);
const handleDatasetChange = (datasetName) => {
dispatch({ type: "SET_ACTIVE_DATASET", payload: { dataset: datasetName } });
};
const handleAPIVersionChange = (apiVersion) => {
dispatch({ type: "SET_ACTIVE_API_VERSION", payload: { apiVersion } });
};
const handleReset = () => {
iframeRef.current && emitReset(iframeRef.current, EDITOR_ORIGIN);
};
const handleCopyQuery = () => query.query && copyQueryUrl(query.query);
const handleEditorResize = () => {
const container = editorContainer.current;
if (!container)
return;
localStorage.setItem(
STORAGE_KEYS.EDITOR_WIDTH,
String(container.clientWidth)
);
};
const responseView = (() => {
if (isFetching) {
return /* @__PURE__ */ React5.createElement(Flex2, { justify: "center", flex: 1, align: "center" }, /* @__PURE__ */ React5.createElement(Spinner, { muted: true }));
}
const execTimeDisplay = rawExecutionTime && /* @__PURE__ */ React5.createElement(
Tooltip2,
{
placement: "right-end",
content: /* @__PURE__ */ React5.createElement(Box5, { padding: 2 }, /* @__PURE__ */ React5.createElement(Text2, null, "Raw execution time of query"))
},
/* @__PURE__ */ React5.createElement("span", null, " (", rawExecutionTime, "ms)")
);
if (fetchParseError || (errorPaths == null ? void 0 : errorPaths.size)) {
let errorView = null;
const scrollToError = (path) => {
const lineEl = document.getElementById(`json-item-${path}`);
if (lineEl instanceof HTMLElement)
lineEl.scrollIntoView({ behavior: "smooth", block: "start" });
};
if (errorPaths) {
errorView = /* @__PURE__ */ React5.createElement(Stack4, { space: 2, flex: 1, paddingX: 3, paddingY: 1 }, /* @__PURE__ */ React5.createElement(Box5, { marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Text2, { weight: "semibold", size: 1 }, "Error parsing:")), [...errorPaths.entries()].map(([path, message]) => /* @__PURE__ */ React5.createElement(
ErrorLineItem,
{
key: path,
onClick: () => scrollToError(path),
padding: 1
},
/* @__PURE__ */ React5.createElement(Text2, { size: 2 }, "`result", formatErrorPath(path), "`: ", message)
)));
} else if (fetchParseError instanceof Error) {
errorView = /* @__PURE__ */ React5.createElement("pre", null, fetchParseError.message);
} else {
errorView = /* @__PURE__ */ React5.createElement("span", null, "Something went wrong...");
}
return /* @__PURE__ */ React5.createElement(Flex2, { flex: 1, direction: "column" }, /* @__PURE__ */ React5.createElement(Split, { mode: "vertical" }, /* @__PURE__ */ React5.createElement(Flex2, { direction: "column", style: { maxHeight: 400 } }, /* @__PURE__ */ React5.createElement(Box5, { marginY: 3, paddingX: 3 }, /* @__PURE__ */ React5.createElement(Label3, { muted: true }, "\u2757Error")), /* @__PURE__ */ React5.createElement(Box5, { flex: 1, overflow: "auto" }, errorView)), /* @__PURE__ */ React5.createElement(Flex2, { flex: 1, direction: "column" }, /* @__PURE__ */ React5.createElement(Box5, { paddingX: 3, marginY: 3 }, /* @__PURE__ */ React5.createElement(Label3, { muted: true }, "Raw Response ", execTimeDisplay)), /* @__PURE__ */ React5.createElement(Box5, { flex: 1, style: { height: "100%" } }, /* @__PURE__ */ React5.createElement(
JSONExplorer,
{
data: rawResponse,
highlightedPaths: errorPaths
}
)))));
}
return /* @__PURE__ */ React5.createElement(Flex2, { flex: 1, direction: "column", style: { maxHeight: "100%" } }, /* @__PURE__ */ React5.createElement(Box5, { padding: 3 }, /* @__PURE__ */ React5.createElement(Label3, { muted: true }, "Query Response ", execTimeDisplay)), parsedResponse ? /* @__PURE__ */ React5.createElement(JSONExplorer, { data: parsedResponse }) : null);
})();
return /* @__PURE__ */ React5.createElement(Flex2, { style: { height: "100%" }, direction: "column" }, /* @__PURE__ */ React5.createElement(Card2, { paddingX: 3, paddingY: 2, borderBottom: true }, /* @__PURE__ */ React5.createElement(Grid, { columns: [6, 6, 12] }, /* @__PURE__ */ React5.createElement(Box5, { padding: 1, column: 2 }, /* @__PURE__ */ React5.createElement(Stack4, null, /* @__PURE__ */ React5.createElement(Card2, { paddingY: 2 }, /* @__PURE__ */ React5.createElement(Label3, { muted: true }, "Dataset")), /* @__PURE__ */ React5.createElement(
Select,
{
value: activeDataset,
onChange: (e) => handleDatasetChange(e.currentTarget.value)
},
datasets.map((ds) => /* @__PURE__ */ React5.createElement("option", { key: ds }, ds))
))), /* @__PURE__ */ React5.createElement(Box5, { padding: 1, column: 2 }, /* @__PURE__ */ React5.createElement(Stack4, null, /* @__PURE__ */ React5.createElement(Card2, { paddingY: 2 }, /* @__PURE__ */ React5.createElement(Label3, { muted: true }, "API Version")), /* @__PURE__ */ React5.createElement(
Select,
{
value: activeAPIVersion,
onChange: (e) => handleAPIVersionChange(e.currentTarget.value)
},
API_VERSIONS.map((v) => /* @__PURE__ */ React5.createElement("option", { key: v }, v))
))), /* @__PURE__ */ React5.createElement(
ShareUrlField,
{
url: windowHref,
title: "Share URL",
column: queryUrl ? 4 : 8,
notificationMessage: "Copied share URL to clipboard!"
}
), queryUrl && /* @__PURE__ */ React5.createElement(
ShareUrlField,
{
url: queryUrl,
title: "Raw Query URL",
notificationMessage: "Copied raw query URL to clipboard!"
}
))), /* @__PURE__ */ React5.createElement(Box5, { flex: 1 }, /* @__PURE__ */ React5.createElement(
Split,
{
style: { width: "100%", height: "100%", overflow: "hidden" },
onDragEnd: handleEditorResize
},
/* @__PURE__ */ React5.createElement(
"div",
{
style: {
width: editorInitialWidth,
minWidth: 200,
height: "100%",
display: "flex",
flexDirection: "column"
},
ref: editorContainer
},
/* @__PURE__ */ React5.createElement("div", { style: { flex: 1, position: "relative" } }, /* @__PURE__ */ React5.createElement(
"iframe",
{
src: EDITOR_URL,
width: "100%",
height: "100%",
style: { border: "none" },
ref: iframeRef
}
), /* @__PURE__ */ React5.createElement("div", { style: { position: "absolute", bottom: 12, left: 12 } }, /* @__PURE__ */ React5.createElement(
Button3,
{
icon: ResetIcon,
text: "Reset",
mode: "ghost",
onClick: handleReset
}
))),
/* @__PURE__ */ React5.createElement(Card2, { paddingTop: 3, paddingBottom: 3, borderTop: true }, /* @__PURE__ */ React5.createElement(Stack4, { space: 3 }, /* @__PURE__ */ React5.createElement(Box5, null, /* @__PURE__ */ React5.createElement(Box5, { paddingX: 3, marginBottom: 1 }, /* @__PURE__ */ React5.createElement(Label3, { muted: true }, "Query", " ", query.query && /* @__PURE__ */ React5.createElement(CopyQueryButton, { onClick: handleCopyQuery, tabIndex: 0 }, "(Copy to clipboard)"))), /* @__PURE__ */ React5.createElement(Flex2, { padding: 3, paddingBottom: 4, overflow: "auto" }, /* @__PURE__ */ React5.createElement(Code, { language: "text" }, query.query), /* @__PURE__ */ React5.createElement(Box5, { width: 3 }))), params && Object.keys(params).length > 0 ? /* @__PURE__ */ React5.createElement(Box5, { paddingX: 3 }, /* @__PURE__ */ React5.createElement(Box5, { marginBottom: 3 }, /* @__PURE__ */ React5.createElement(Label3, { muted: true }, "Params")), /* @__PURE__ */ React5.createElement(Stack4, { space: 3, marginLeft: 3 }, Object.entries(params).map(([key, value]) => /* @__PURE__ */ React5.createElement(Text2, { key, size: 2, muted: true }, "$", key, ": ", value)))) : null)),
/* @__PURE__ */ React5.createElement(Card2, { padding: 3, borderTop: true }, /* @__PURE__ */ React5.createElement(
Button3,
{
tone: "primary",
icon: PlayIcon,
text: "Fetch",
fontSize: [2],
padding: [3],
style: { width: "100%" },
onClick: () => handleRun(query, params),
disabled: !query.query
}
))
),
/* @__PURE__ */ React5.createElement(
Box5,
{
style: {
width: `calc(100% - ${editorInitialWidth}px)`,
minWidth: 100,
display: "flex",
flexDirection: "column"
}
},
/* @__PURE__ */ React5.createElement(Flex2, { flex: 1, direction: "column", overflow: "hidden" }, responseView)
)
)));
}
var _a;
var EDITOR_URL = typeof process !== "undefined" && ((_a = process == null ? void 0 : process.env) == null ? void 0 : _a.SANITY_STUDIO_GROQD_PLAYGROUND_ENV) === "development" ? "http://localhost:3069" : "https://unpkg.com/groqd-playground-editor@0.0.6/build/index.html";
var EDITOR_ORIGIN = new URL(EDITOR_URL).origin;
var reducer = (state, action) => {
switch (action.type) {
case "INPUT_EVAL_SUCCESS":
return __spreadProps(__spreadValues({}, state), {
query: action.payload.query,
params: action.payload.params,
inputParseError: void 0
});
case "INPUT_PARSE_FAILURE":
return __spreadProps(__spreadValues({}, state), {
inputParseError: action.payload.inputParseError
});
case "MAKE_FETCH_REQUEST":
return __spreadProps(__spreadValues({}, state), {
isFetching: true,
queryUrl: action.payload.queryUrl
});
case "RAW_RESPONSE_RECEIVED":
return __spreadProps(__spreadValues({}, state), {
isFetching: false,
rawResponse: action.payload.rawResponse,
rawExecutionTime: action.payload.execTime
});
case "FETCH_RESPONSE_PARSED":
return __spreadProps(__spreadValues({}, state), {
parsedResponse: action.payload.parsedResponse,
fetchParseError: void 0,
errorPaths: void 0
});
case "FETCH_PARSE_FAILURE":
return __spreadProps(__spreadValues({}, state), {
isFetching: false,
fetchParseError: action.payload.fetchParseError,
errorPaths: action.payload.errorPaths
});
case "SET_ACTIVE_API_VERSION":
localStorage.setItem(STORAGE_KEYS.API_VERSION, action.payload.apiVersion);
return __spreadProps(__spreadValues({}, state), { activeAPIVersion: action.payload.apiVersion });
case "SET_ACTIVE_DATASET":
localStorage.setItem(STORAGE_KEYS.DATASET, action.payload.dataset);
return __spreadProps(__spreadValues({}, state), { activeDataset: action.payload.dataset });
default:
return state;
}
};
var EDITOR_INITIAL_WIDTH = 500;
var readySchema = z.object({
event: z.literal("READY")
});
var inputSchema = z.object({
event: z.literal("INPUT"),
compressedRawCode: z.string(),
code: z.string(),
requestImmediateFetch: z.boolean().optional().default(false),
requestShareCopy: z.boolean().optional().default(false)
});
var errorSchema = z.object({
event: z.literal("ERROR"),
message: z.string()
});
var messageSchema = z.union([inputSchema, errorSchema, readySchema]);
var url = new URL(window.location.href);
var setQP = (key, value) => {
url.searchParams.set(key, value);
window.history.replaceState(null, "", url);
};
// src/PlaygroundWrapper.tsx
function GroqdPlaygroundWrapper(props) {
return /* @__PURE__ */ React6.createElement(ToastProvider, null, /* @__PURE__ */ React6.createElement(GroqdPlayground, __spreadValues({}, props)));
}
export {
GroqdPlaygroundWrapper as default
};
//# sourceMappingURL=PlaygroundWrapper-HYDTOGJO.mjs.map