Author SHA1 Message Date
James Ritchie c57d313b6d Merge pull request #80 from jsonhero-io/font-swap
Swapped mono font to Roboto Mono
2022-06-13 11:16:24 +01:00
James Ritchie c504b0c8c6 Change the mono spaced font to roboto mono 2022-06-13 10:31:39 +01:00
Eric Allam dc3bb5d2ab Merge branch 'sascha10000-feature/76-better-handle-long-key-names' 2022-06-10 15:06:58 +01:00
sascha10000 4c810901c3 -Added ellipsis in column and line-break in the InfoPanel 2022-06-09 23:48:34 +02:00
Eric Allam 25e1b20d9c Remove Chrome extension banner 2022-06-09 15:12:05 +01:00
Eric Allam 52b7d1962d Ensure text is shown during custom font load 2022-06-09 14:52:10 +01:00
Eric Allam d4c03f38d2 Cache static assets in the browser using remix asset imports 2022-06-09 14:16:10 +01:00
Eric Allam e37607b377 Remove PH banner 2022-06-09 12:39:02 +01:00
James Ritchie abd804ca4e Fixed PH banner mobile layout 2022-06-08 08:37:11 +01:00
Eric Allam ac31a5a1cf PH launch 2022-06-08 07:39:57 +01:00
Eric Allam a53506564d A nasty workaround for IPFS previewing 2022-06-07 14:13:24 +01:00
James Ritchie 2cb9bcd991 Reverted PH badge for now 2022-06-07 13:59:56 +01:00
James Ritchie d7225b201f Added Product Hunt Banner to homepage 2022-06-07 13:56:34 +01:00
Eric Allam 0358dbd5e2 Add some logging to discover what cloudflare is doing 2022-06-07 13:55:46 +01:00
Eric Allam bc5e5561c7 Fixed previewing IPFS images in cloudflare 2022-06-07 13:49:40 +01:00
Eric Allam 6df767080a IPFS previews work without the extension 2022-06-07 13:37:43 +01:00
sascha10000 2fb902ee01 fixed error due to issue with server sided preview generation (#70) 2022-06-07 13:15:18 +01:00
Eric AllamandJames Ritchie fa7010da0b Chrome extension banner (#74)
* Added chrome extension banner

* Only show the chrome banner when in Chrome

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2022-06-06 14:11:20 +01:00
Eric AllamandJames Ritchie 1b42269739 GitHub button footer in minimal mode (#72)
* Added a new github star button to the footer

* Improved the props to work the same as hero icons

* Only show the github link in the footer if on minimal theme

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2022-06-06 11:38:55 +01:00
Eric Allam c9d309c16d Fixed tree view minimal height 2022-06-01 15:22:11 +01:00
Eric Allam 3acf393009 Added privacy policy for jsonhero.io 2022-06-01 12:05:08 +01:00
Eric Allam 7508a96d3f Support minimal theme to strip out the header (for the chrome extension) 2022-06-01 11:28:24 +01:00
Eric Allam 49e0c57a33 Add ability to override the theme with a query param 2022-05-26 14:40:31 +01:00
Eric Allam d898d820bb Allow clients in browsers to call the create API 2022-05-26 09:15:33 +01:00
Eric Allam a4b7a38e67 Upgrade to miniflare 2.4.0 to fix issue with Node.js 17.7+ 2022-05-18 09:36:11 +01:00
Eric Allam d722b915a9 Ability to preview ipfs images 2022-05-17 16:26:10 +01:00
Eric Allam b3515bfff0 Display related values on Array and Object paths as well 2022-05-13 10:05:11 +01:00
42 changed files with 893 additions and 284 deletions

Before

Width:  |  Height:  |  Size: 620 KiB

After

Width:  |  Height:  |  Size: 620 KiB

Before

Width:  |  Height:  |  Size: 279 B

After

Width:  |  Height:  |  Size: 279 B

Before

Width:  |  Height:  |  Size: 336 B

After

Width:  |  Height:  |  Size: 336 B

Before

Width:  |  Height:  |  Size: 486 B

After

Width:  |  Height:  |  Size: 486 B

+6 -1
View File
@@ -6,6 +6,7 @@ import {
ViewUpdate,
} from "@uiw/react-codemirror";
import { useRef, useEffect } from "react";
import { useJsonDoc } from "~/hooks/useJsonDoc";
import { getEditorSetup } from "~/utilities/codeMirrorSetup";
import { darkTheme, lightTheme } from "~/utilities/codeMirrorTheme";
import { useTheme } from "./ThemeProvider";
@@ -92,10 +93,14 @@ export function CodeEditor(opts: CodeEditorProps) {
}
}, [selection, view, setSelectionRef.current]);
const { minimal } = useJsonDoc();
return (
<div>
<div
className="h-jsonViewerHeight overflow-y-auto no-scrollbar"
className={`${
minimal ? "h-jsonViewerHeightMinimal" : "h-jsonViewerHeight"
} overflow-y-auto no-scrollbar`}
ref={editor}
/>
</div>
+8 -2
View File
@@ -3,6 +3,7 @@ import { colorForItemAtPath } from "~/utilities/colors";
import { IconComponent } from "~/useColumnView";
import { useJson } from "../hooks/useJson";
import { memo, useMemo } from "react";
import { useJsonDoc } from "~/hooks/useJsonDoc";
export type ColumnProps = {
id: string;
@@ -15,6 +16,7 @@ export type ColumnProps = {
function ColumnElement(column: ColumnProps) {
const { id, title, children } = column;
const [json] = useJson();
const { minimal } = useJsonDoc();
const iconColor = useMemo(() => colorForItemAtPath(id, json), [id, json]);
return (
@@ -25,9 +27,13 @@ function ColumnElement(column: ColumnProps) {
>
<div className="flex items-center text-slate-800 bg-slate-50 mb-[3px] p-2 pb-0 transition dark:bg-slate-900 dark:text-slate-300">
{column.icon && <column.icon className="h-6 w-6 mr-1" />}
<Title className="">{title}</Title>
<Title className="text-ellipsis overflow-hidden">{title}</Title>
</div>
<div className="overflow-y-auto h-viewerHeight no-scrollbar">
<div
className={`overflow-y-auto ${
minimal ? "h-viewerHeightMinimal" : "h-viewerHeight"
} no-scrollbar`}
>
{children}
</div>
</div>
+14 -1
View File
@@ -1,11 +1,15 @@
import { useJsonDoc } from "~/hooks/useJsonDoc";
import { ArrowKeysIcon } from "./Icons/ArrowKeysIcon";
import { CopyShortcutIcon } from "./Icons/CopyShortcutIcon";
import { EscapeKeyIcon } from "./Icons/EscapeKeyIcon";
import { SquareBracketsIcon } from "./Icons/SquareBracketsIcon";
import { Body } from "./Primitives/Body";
import { ThemeModeToggler } from "./ThemeModeToggle";
import { GithubStarSmall } from "./UI/GithubStarSmall";
export function Footer() {
const { minimal } = useJsonDoc();
return (
<footer className="flex items-center justify-between w-screen h-[30px] bg-slate-200 dark:bg-slate-800 border-t-[1px] border-slate-400 transition dark:border-slate-600">
<ol className="flex pl-3">
@@ -34,7 +38,16 @@ export function Footer() {
</Body>
</li>
</ol>
<ThemeModeToggler />
<ol className="flex items-center">
{minimal && (
<li>
<GithubStarSmall />
</li>
)}
<li>
<ThemeModeToggler />
</li>
</ol>
</footer>
);
}
@@ -3,6 +3,8 @@ import { ExtraLargeTitle } from "../Primitives/ExtraLargeTitle";
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
import { HomeSection } from "./HomeSection";
import shareVideo from "~/assets/home/JsonHeroShare.mp4";
export function HomeCollaborateSection() {
return (
<HomeSection
@@ -20,7 +22,7 @@ export function HomeCollaborateSection() {
</SmallSubtitle>
</div>
<div className="w-full md:w-1/2">
<AutoplayVideo src="/home/JsonHeroShare.mp4" />
<AutoplayVideo src={shareVideo} />
</div>
</HomeSection>
);
+3 -1
View File
@@ -3,6 +3,8 @@ import { ExtraLargeTitle } from "../Primitives/ExtraLargeTitle";
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
import { HomeSection } from "./HomeSection";
import edgeCasesVideo from "~/assets/home/UncoverEdgeCases.mp4";
export function HomeEdgeCasesSection() {
return (
<HomeSection
@@ -21,7 +23,7 @@ export function HomeEdgeCasesSection() {
</SmallSubtitle>
</div>
<div className="w-full md:w-1/2">
<AutoplayVideo src="/home/UncoverEdgeCases.mp4" />
<AutoplayVideo src={edgeCasesVideo} />
</div>
</HomeSection>
);
+5
View File
@@ -1,3 +1,4 @@
import { Link } from "remix";
import { DiscordIcon } from "../Icons/DiscordIcon";
import { EmailIcon } from "../Icons/EmailIcon";
import { GithubIcon } from "../Icons/GithubIcon";
@@ -42,6 +43,10 @@ export function HomeFooter({ maxWidth = "1150px" }: HomeFooterProps) {
<TwitterIcon />
</a>
</li>
<li className="ml-2 hover:cursor-pointer text-indigo-700">
<Link to="/privacy">Privacy Policy</Link>
</li>
</ol>
</div>
</footer>
+6 -2
View File
@@ -11,9 +11,13 @@ import {
PopoverTrigger,
} from "../UI/Popover";
export function HomeHeader() {
export function HomeHeader({ fixed }: { fixed?: boolean }) {
return (
<header className="fixed z-20 flex items-center justify-between w-screen h-[82px] px-4 bg-indigo-700">
<header
className={`${
fixed ? "fixed" : ""
} z-20 flex items-center justify-between w-screen h-[82px] px-4 bg-indigo-700`}
>
<div className="flex w-36 sm:w-44 mr-3">
<Logo />
</div>
+3 -2
View File
@@ -2,7 +2,8 @@ import { AutoplayVideo } from "../AutoplayVideo";
import { NewFile } from "../NewFile";
import { ExtraLargeTitle } from "../Primitives/ExtraLargeTitle";
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
import { HomeSection } from "./HomeSection";
import heroVideo from "~/assets/home/JsonHero2.mp4";
const jsonHeroTitle = "JSON sucks.";
const jsonHeroSlogan = "But we're making it better.";
@@ -14,7 +15,7 @@ export function HomeHeroSection() {
>
<div className="self-center md:w-1/2 md:pr-10 flex justify-end">
<div className=" max-w-3xl">
<AutoplayVideo src="/home/JsonHero2.mp4" />
<AutoplayVideo src={heroVideo} />
</div>
</div>
<div className="self-center flex align-center md:w-1/2 px-6 pb-8 mt-8 lg:mt-0">
+3 -1
View File
@@ -3,6 +3,8 @@ import { ExtraLargeTitle } from "../Primitives/ExtraLargeTitle";
import { SmallSubtitle } from "../Primitives/SmallSubtitle";
import { HomeSection } from "./HomeSection";
import searchVideo from "~/assets/home/JsonHeroSearch.mp4";
export function HomeSearchSection() {
return (
<HomeSection containerClassName="py-10 px-6 bg-black md:py-36 lg:py-20">
@@ -17,7 +19,7 @@ export function HomeSearchSection() {
</SmallSubtitle>
</div>
<div className="w-full md:w-1/2">
<AutoplayVideo src="/home/JsonHeroSearch.mp4" />
<AutoplayVideo src={searchVideo} />
</div>
</HomeSection>
);
+8 -4
View File
@@ -1,11 +1,15 @@
export function GithubIconSimple(props: React.SVGProps<SVGSVGElement>) {
export type IconProps = {
className?: string;
};
export function GithubIconSimple({ className }: IconProps) {
return (
<svg
className={props.className}
className={className}
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_571_3822)">
@@ -13,7 +17,7 @@ export function GithubIconSimple(props: React.SVGProps<SVGSVGElement>) {
fillRule="evenodd"
clipRule="evenodd"
d="M12 0C5.37017 0 0 5.50708 0 12.306C0 17.745 3.44015 22.3532 8.20626 23.9849C8.80295 24.0982 9.02394 23.7205 9.02394 23.3881C9.02394 23.0935 9.01657 22.3229 9.00921 21.2956C5.67219 22.0359 4.96501 19.6487 4.96501 19.6487C4.41989 18.2285 3.63168 17.8508 3.63168 17.8508C2.54144 17.0878 3.71271 17.1029 3.71271 17.1029C4.91344 17.1936 5.55433 18.372 5.55433 18.372C6.62247 20.2531 8.36096 19.7092 9.04604 19.3919C9.15654 18.5987 9.46593 18.0548 9.80479 17.745C7.13812 17.4353 4.33886 16.3777 4.33886 11.6638C4.33886 10.3192 4.80295 9.2238 5.57643 8.36261C5.4512 8.05288 5.03867 6.79887 5.69429 5.1067C5.69429 5.1067 6.7035 4.77432 8.99447 6.36827C9.95212 6.09632 10.9761 5.96034 12 5.95279C13.0166 5.95279 14.0479 6.09632 15.0055 6.36827C17.2965 4.77432 18.3057 5.1067 18.3057 5.1067C18.9613 6.79887 18.5488 8.05288 18.4236 8.36261C19.1897 9.2238 19.6538 10.3192 19.6538 11.6638C19.6538 16.3928 16.8471 17.4278 14.1731 17.7375C14.6004 18.1152 14.9908 18.8706 14.9908 20.0189C14.9908 21.6657 14.9761 22.9877 14.9761 23.3957C14.9761 23.728 15.1897 24.1058 15.8011 23.9849C20.5672 22.3532 24 17.745 24 12.3135C24 5.50708 18.6298 0 12 0Z"
fill="#231E1B"
fill="currentColor"
/>
</g>
<defs>
+4 -3
View File
@@ -6,11 +6,11 @@ import { useJsonColumnViewState } from "~/hooks/useJsonColumnView";
import { concatenated, getHierarchicalTypes } from "~/utilities/dataType";
import { formatRawValue } from "~/utilities/formatter";
import { isNullable } from "~/utilities/nullable";
import { CopyTextButton } from "./CopyTextButton";
import { Body } from "./Primitives/Body";
import { LargeMono } from "./Primitives/LargeMono";
import { Title } from "./Primitives/Title";
import { ValueIcon, ValueIconSize } from "./ValueIcon";
import { CopyTextButton } from "./CopyTextButton";
export type InfoHeaderProps = {
relatedPaths: string[];
@@ -41,12 +41,13 @@ export function InfoHeader({ relatedPaths }: InfoHeaderProps) {
}, [relatedPaths, json]);
const [hovering, setHovering] = useState(false);
console.warn(selectedInfo);
return (
<div className="mb-4 pb-4">
<div className="flex items-center">
<Title className="flex-1 mr-2 text-slate-700 transition dark:text-slate-200">
{selectedName ?? "nothing"}
<Title className="flex-1 mr-2 overflow-hidden overflow-ellipsis break-words text-slate-700 transition dark:text-slate-200">
{ selectedName ?? "nothing" }
</Title>
<div>
<ValueIcon
+8 -10
View File
@@ -4,27 +4,25 @@ import { PropertiesValue } from "./Properties/PropertiesValue";
import { InfoHeader } from "./InfoHeader";
import { ContainerInfo } from "./ContainerInfo";
import { useSelectedInfo } from "~/hooks/useSelectedInfo";
import { useMemo } from "react";
import { useJson } from "~/hooks/useJson";
import { getRelatedPathsAtPath } from "~/utilities/relatedValues";
import { useJsonColumnViewState } from "~/hooks/useJsonColumnView";
import { useRelatedPaths } from "~/hooks/useRelatedPaths";
import { useJsonDoc } from "~/hooks/useJsonDoc";
export function InfoPanel() {
const { minimal } = useJsonDoc();
const selectedInfo = useSelectedInfo();
const { selectedNodeId } = useJsonColumnViewState();
const relatedPaths = useRelatedPaths();
if (!selectedInfo) {
return <></>;
}
const isSelectedLeafNode =
selectedInfo.name !== "object" && selectedInfo.name !== "array";
return (
<>
<div className="h-inspectorHeight p-4 bg-white border-l-[1px] border-slate-300 overflow-y-auto no-scrollbar transition dark:bg-slate-800 dark:border-slate-600">
<div
className={`${
minimal ? "h-inspectorHeightMinimal" : "h-inspectorHeight"
} p-4 bg-white border-l-[1px] border-slate-300 overflow-y-auto no-scrollbar transition dark:bg-slate-800 dark:border-slate-600`}
>
<InfoHeader relatedPaths={relatedPaths} />
<div className="mb-4">
@@ -34,7 +32,7 @@ export function InfoPanel() {
<ContainerInfo />
{isSelectedLeafNode && <RelatedValues relatedPaths={relatedPaths} />}
<RelatedValues relatedPaths={relatedPaths} />
</div>
</>
);
+4 -1
View File
@@ -4,6 +4,7 @@ import {
useJsonColumnViewAPI,
useJsonColumnViewState,
} from "~/hooks/useJsonColumnView";
import { useJsonDoc } from "~/hooks/useJsonDoc";
import { JsonTreeViewNode, useJsonTreeViewContext } from "~/hooks/useJsonTree";
import { VirtualNode } from "~/hooks/useVirtualTree";
import { CopySelectedNodeShortcut } from "./CopySelectedNode";
@@ -78,6 +79,8 @@ export function JsonTreeView() {
}
}, [treeRef.current]);
const { minimal } = useJsonDoc();
return (
<>
<CopySelectedNodeShortcut />
@@ -85,7 +88,7 @@ export function JsonTreeView() {
className="text-white w-full"
ref={parentRef}
style={{
height: `calc(100vh - 106px)`,
height: `calc(100vh - ${minimal ? "66px" : "106px"})`,
overflowY: "auto",
overflowX: "hidden",
}}
+3 -1
View File
@@ -4,6 +4,8 @@ import { useJsonColumnViewAPI } from "~/hooks/useJsonColumnView";
import { ColumnViewNode, IconComponent } from "~/useColumnView";
import { Body } from "./Primitives/Body";
import eyeIcon from "~/assets/svgs/EyeIcon.svg";
export type PathPreviewProps = {
nodes: ColumnViewNode[];
maxComponents?: number;
@@ -77,7 +79,7 @@ export function PathPreview({
<div
className={`flex select-none pl-7 ${
isEnabled
? "relative transition hover:bg-slate-200 hover:cursor-pointer dark:hover:bg-slate-600 after:transition after:absolute after:h-3 after:w-3 after:opacity-0 hover:after:opacity-100 after:top-1 after:left-1 after:content-[''] after:bg-[url('/svgs/EyeIcon.svg')] after:bg-no-repeat"
? `relative transition hover:bg-slate-200 hover:cursor-pointer dark:hover:bg-slate-600 after:transition after:absolute after:h-3 after:w-3 after:opacity-0 hover:after:opacity-100 after:top-1 after:left-1 after:content-[''] after:bg-[url('${eyeIcon}')] after:bg-no-repeat`
: "disabled"
}`}
onClick={() =>
@@ -0,0 +1,18 @@
import { PreviewImageUri } from "./PreviewImageUri";
export function PreviewIPFSImage({ src }: { src: URL }) {
const newSrc = createPreviewIPFSImageURL(src);
return <PreviewImageUri src={newSrc} />;
}
const createPreviewIPFSImageURL = (src: URL): string => {
const url = new URL(src.href);
url.protocol = "https:";
url.pathname = `/ipfs/${src.pathname.substring(1)}`;
url.hostname = "ipfs.io";
// Remove the leading slash
return url.href;
};
@@ -6,11 +6,11 @@ export function PreviewImageUri({
contentType,
}: {
src: string;
contentType: string;
contentType?: string;
}) {
return (
<div>
<PreviewBox>
<PreviewBox link={src}>
<Body>
<img src={src} />
</Body>
+13 -6
View File
@@ -9,6 +9,7 @@ import { PreviewBox } from "../PreviewBox";
import { PreviewAudioUri } from "./PreviewAudioUri";
import { PreviewDate } from "./PreviewDate";
import { PreviewImageUri } from "./PreviewImageUri";
import { PreviewIPFSImage } from "./PreviewIPFSImage";
import { PreviewUri } from "./PreviewUri";
import { PreviewVideoUri } from "./PreviewVideoUri";
@@ -26,12 +27,18 @@ export function PreviewString({ info }: { info: JSONStringType }) {
info.format.contentType === "image/svg+xml" ||
info.format.contentType === "image/webp"
) {
return (
<PreviewImageUri
src={info.value}
contentType={info.format.contentType}
/>
);
const url = new URL(info.value);
if (url.protocol === "ipfs:") {
return <PreviewIPFSImage src={url} />;
} else {
return (
<PreviewImageUri
src={info.value}
contentType={info.format.contentType}
/>
);
}
} else if (
info.format.contentType === "video/mp4" ||
info.format.contentType === "video/webm" ||
+9 -1
View File
@@ -23,7 +23,15 @@ export function PreviewUri(props: PreviewUriProps) {
<div>
{previewFetcher.type === "done" ? (
<>
{"error" in previewFetcher.data ? (
{typeof previewFetcher.data == "string" ? (
<PreviewBox>
<Body>
<span
dangerouslySetInnerHTML={{ __html: previewFetcher.data }}
></span>
</Body>
</PreviewBox>
) : "error" in previewFetcher.data ? (
<PreviewBox>
<Body>{previewFetcher.data.error}</Body>
</PreviewBox>
+20 -2
View File
@@ -6,6 +6,7 @@ import { useJsonDoc } from "~/hooks/useJsonDoc";
import { ToolTip } from "./ToolTip";
import { Body } from "./Primitives/Body";
import { ShortcutIcon } from "./Icons/ShortcutIcon";
import { useTheme } from "./ThemeProvider";
export function SideBar() {
const { doc } = useJsonDoc();
@@ -81,6 +82,23 @@ function SidebarLink({
const isActive = location.pathname === to;
const { minimal } = useJsonDoc();
const [theme] = useTheme();
const queryParams = new URLSearchParams();
if (typeof minimal === "boolean") {
queryParams.set("minimal", String(minimal));
if (theme) {
queryParams.set("theme", theme);
}
}
const href = `${to}${
queryParams.toString().length > 0 ? `?${queryParams.toString()}` : ""
}`;
if (hotKey) {
const navigate = useNavigate();
useHotkeys(
@@ -88,7 +106,7 @@ function SidebarLink({
(e) => {
e.preventDefault();
if (!isActive && to) {
navigate(to);
navigate(href);
}
},
[navigate, isActive, to]
@@ -100,7 +118,7 @@ function SidebarLink({
: "relative w-10 h-10 mb-1 text-slate-700 hover:bg-slate-300 rounded-sm cursor:pointer transition dark:text-white dark:hover:bg-slate-700";
return !!to ? (
<Link to={to} prefetch={isActive ? "none" : "render"}>
<Link to={href} prefetch={isActive ? "none" : "render"}>
<li className={classes}>{children}</li>
</Link>
) : (
+4 -2
View File
@@ -15,8 +15,10 @@ export function ThemeModeToggler() {
return (
<button
className={`flex text-xl items-center pr-2 ${
theme === "light" ? "text-slate-800" : "text-white"
className={`flex text-xl items-center px-2 py-1.5 transition ${
theme === "light"
? "text-slate-800 hover:bg-slate-300"
: "text-white hover:bg-slate-700"
}`}
onClick={toggleTheme}
>
+34
View File
@@ -0,0 +1,34 @@
import { formatStarCount } from "~/utilities/formatStarCount";
import { GithubIconSimple } from "../Icons/GithubIconSimple";
import { Body } from "../Primitives/Body";
import { useStarCount } from "../StarCountProvider";
export type GithubStarSmallProps = {
className?: string;
};
export function GithubStarSmall({ className }: GithubStarSmallProps) {
const starCount = useStarCount();
return (
<a
href="https://github.com/jsonhero-io/jsonhero-web"
target="_blank"
className="flex p-1 text-slate-700 dark:text-slate-300 hover:bg-slate-300 dark:hover:bg-slate-700 transition hover:cursor-pointer"
>
<div className="flex items-center gap-1.5 pl-1 rounded-l-sm">
<GithubIconSimple className="w-4 h-4 ml-1 text-slate-700 dark:text-white transition"></GithubIconSimple>
<Body className="font-semibold text-slate-800 dark:text-slate-100">
Star
</Body>
</div>
{starCount && (
<div className="pr-2 pl-1">
<Body className="font-bold dark:text-slate-100">
{formatStarCount(starCount)}
</Body>
</div>
)}
</a>
);
}
+4 -1
View File
@@ -5,6 +5,7 @@ import { JSONDocument } from "~/jsonDoc.server";
type JsonDocType = {
doc: JSONDocument;
path?: string;
minimal?: boolean;
};
const JsonDocContext = createContext<JsonDocType | undefined>(undefined);
@@ -13,13 +14,15 @@ export function JsonDocProvider({
children,
doc,
path,
minimal,
}: {
children: ReactNode;
doc: JSONDocument;
path?: string;
minimal?: boolean;
}) {
return (
<JsonDocContext.Provider value={{ doc, path }}>
<JsonDocContext.Provider value={{ doc, path, minimal }}>
{children}
</JsonDocContext.Provider>
);
+18 -4
View File
@@ -18,6 +18,8 @@ import {
useTheme,
} from "~/components/ThemeProvider";
import openGraphImage from "~/assets/images/opengraph.png";
export const meta: MetaFunction = ({ location }) => {
const description =
"JSON Hero makes reading and understand JSON files easy by giving you a clean and beautiful UI packed with extra features.";
@@ -25,11 +27,11 @@ export const meta: MetaFunction = ({ location }) => {
title: "JSON Viewer - JSON Hero",
viewport: "width=device-width,initial-scale=1",
description,
"og:image": `https://jsonhero.io/images/opengraph.png`,
"og:image": `https://jsonhero.io${openGraphImage}`,
"og:url": `https://jsonhero.io${location.pathname}`,
"og:title": "JSON Hero - A beautiful JSON viewer",
"og:description": description,
"twitter:image": "https://jsonhero.io/images/opengraph.png",
"twitter:image": `https://jsonhero.io${openGraphImage}`,
"twitter:card": "summary_large_image",
"twitter:creator": "@json_hero",
"twitter:site": "@json_hero",
@@ -50,20 +52,32 @@ export function links() {
export type LoaderData = {
theme?: Theme;
starCount?: number;
themeOverride?: Theme;
};
export const loader: LoaderFunction = async ({ request }) => {
const themeSession = await getThemeSession(request);
const starCount = await getStarCount();
const themeOverride = getThemeFromRequest(request);
const data: LoaderData = {
theme: themeSession.getTheme(),
starCount,
themeOverride,
};
return data;
};
function getThemeFromRequest(request: Request): Theme | undefined {
const url = new URL(request.url);
const theme = url.searchParams.get("theme");
if (theme) {
return theme as Theme;
}
return undefined;
}
function App() {
const [theme] = useTheme();
@@ -86,7 +100,7 @@ function App() {
}
export default function AppWithProviders() {
const { theme, starCount } = useLoaderData<LoaderData>();
const { theme, starCount, themeOverride } = useLoaderData<LoaderData>();
const location = useLocation();
@@ -96,7 +110,7 @@ export default function AppWithProviders() {
return (
<ThemeProvider
specifiedTheme={theme}
themeOverride={forceDarkMode ? "dark" : undefined}
themeOverride={forceDarkMode ? "dark" : themeOverride}
>
<StarCountProvider starCount={starCount}>
<App />
+23 -2
View File
@@ -1,8 +1,22 @@
import { ActionFunction, json } from "remix";
import { ActionFunction, json, LoaderFunction } from "remix";
import invariant from "tiny-invariant";
import { sendEvent } from "~/graphJSON.server";
import { createFromRawJson, CreateJsonOptions } from "~/jsonDoc.server";
export const loader: LoaderFunction = async ({ request }) => {
if (request.method === "OPTIONS") {
return new Response(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Max-Age": "86400",
},
});
}
};
export const action: ActionFunction = async ({ request, context }) => {
const url = new URL(request.url);
@@ -42,5 +56,12 @@ export const action: ActionFunction = async ({ request, context }) => {
})
);
return json({ id: doc.id, title, location: url.toString() });
return json(
{ id: doc.id, title, location: url.toString() },
{
headers: {
"Access-Control-Allow-Origin": "*",
},
}
);
};
+1 -1
View File
@@ -11,7 +11,7 @@ import { GithubBanner } from "~/components/Home/HomeGithubBanner";
export default function Index() {
return (
<div className="overflow-x-hidden">
<HomeHeader />
<HomeHeader fixed={true} />
<HomeHeroSection />
<GithubBanner />
<HomeInfoBoxSection />
+23 -2
View File
@@ -41,6 +41,7 @@ export const loader: LoaderFunction = async ({ params, request }) => {
}
const path = getPathFromRequest(request);
const minimal = getMinimalFromRequest(request);
if (doc.type == "url") {
console.log(`Fetching ${doc.url}...`);
@@ -65,12 +66,14 @@ export const loader: LoaderFunction = async ({ params, request }) => {
doc,
json,
path,
minimal,
};
} else {
return {
doc,
json: JSON.parse(doc.contents),
path,
minimal,
};
}
};
@@ -91,7 +94,24 @@ function getPathFromRequest(request: Request): string | null {
return `$.${path}`;
}
type LoaderData = { doc: JSONDocument; json: unknown; path?: string };
function getMinimalFromRequest(request: Request): boolean | undefined {
const url = new URL(request.url);
const minimal = url.searchParams.get("minimal");
if (!minimal) {
return;
}
return minimal === "true";
}
type LoaderData = {
doc: JSONDocument;
json: unknown;
path?: string;
minimal?: boolean;
};
export const meta: MetaFunction = ({
data,
@@ -124,6 +144,7 @@ export default function JsonDocumentRoute() {
doc={loaderData.doc}
path={loaderData.path}
key={loaderData.doc.id}
minimal={loaderData.minimal}
>
<JsonProvider initialJson={loaderData.json}>
<JsonSchemaProvider>
@@ -145,7 +166,7 @@ export default function JsonDocumentRoute() {
</div>
</div>
<div className="h-screen flex flex-col sm:overflow-hidden">
<Header />
{!loaderData.minimal && <Header />}
<div className="bg-slate-50 flex-grow transition dark:bg-slate-900">
<div className="main-container flex justify-items-stretch h-full">
<SideBar />
+310
View File
@@ -0,0 +1,310 @@
---
meta:
title: JSON Hero - Privacy
---
import { HomeHeader } from "~/components/Home/HomeHeader";
<HomeHeader />
<div style={{width: "800px", marginLeft: "12px", marginTop: "12px", marginBottom: "12px"}}>
**PRIVACY NOTICE**
<br />
### Last updated June 01, 2022
<br />
This privacy notice for Stack Hero Limited ("Company," "we," "us," or "our"), describes how and why we might collect, store, use, and/or share ("process") your information when you use our services ("Services"), such as when you:
Visit our website at https://jsonhero.io, or any website of ours that links to this privacy notice
Engage with us in other related ways, including any sales, marketing, or events
Questions or concerns? Reading this privacy notice will help you understand your privacy rights and choices. If you do not agree with our policies and practices, please do not use our Services. If you still have any questions or concerns, please contact us at hello@jsonhero.io.
<br />
**SUMMARY OF KEY POINTS**
<br />
This summary provides key points from our privacy notice, but you can find out more details about any of these topics by clicking the link following each key point or by using our table of contents below to find the section you are looking for. You can also click here to go directly to our table of contents.
<br />
What personal information do we process? When you visit, use, or navigate our Services, we may process personal information depending on how you interact with Stack Hero Limited and the Services, the choices you make, and the products and features you use. Click here to learn more.
<br />
Do we process any sensitive personal information? We may process sensitive personal information when necessary with your consent or as otherwise permitted by applicable law. Click here to learn more.
<br />
Do we receive any information from third parties? We do not receive any information from third parties.
<br />
How do we process your information? We process your information to provide, improve, and administer our Services, communicate with you, for security and fraud prevention, and to comply with law. We may also process your information for other purposes with your consent. We process your information only when we have a valid legal reason to do so. Click here to learn more.
<br />
In what situations and with which parties do we share personal information? We may share information in specific situations and with specific third parties. Click here to learn more.
<br />
How do we keep your information safe? We have organizational and technical processes and procedures in place to protect your personal information. However, no electronic transmission over the internet or information storage technology can be guaranteed to be 100% secure, so we cannot promise or guarantee that hackers, cybercriminals, or other unauthorized third parties will not be able to defeat our security and improperly collect, access, steal, or modify your information. Click here to learn more.
<br />
What are your rights? Depending on where you are located geographically, the applicable privacy law may mean you have certain rights regarding your personal information. Click here to learn more.
<br />
How do I exercise my rights? The easiest way to exercise your rights is by filling out our data subject request form available here: hello@jsonhero.io, or by contacting us. We will consider and act upon any request in accordance with applicable data protection laws.
<br />
Want to learn more about what Stack Hero Limited does with any information we collect? Click here to review the notice in full.
<br />
**1. WHAT INFORMATION DO WE COLLECT?**
<br />
In Short: We collect personal information that you provide to us.
<br />
We collect personal information that you voluntarily provide to us when you express an interest in obtaining information about us or our products and Services, when you participate in activities on the Services, or otherwise when you contact us.
<br />
Sensitive Information. When necessary, with your consent or as otherwise permitted by applicable law, we process the following categories of sensitive information:
All personal information that you provide to us must be true, complete, and accurate, and you must notify us of any changes to such personal information.
<br />
Information automatically collected
<br />
In Short: Some information — such as your Internet Protocol (IP) address and/or browser and device characteristics — is collected automatically when you visit our Services.
<br />
We automatically collect certain information when you visit, use, or navigate the Services. This information does not reveal your specific identity (like your name or contact information) but may include device and usage information, such as your IP address, browser and device characteristics, operating system, language preferences, referring URLs, device name, country, location, information about how and when you use our Services, and other technical information. This information is primarily needed to maintain the security and operation of our Services, and for our internal analytics and reporting purposes.
<br />
Like many businesses, we also collect information through cookies and similar technologies.
<br />
The information we collect includes:
Log and Usage Data. Log and usage data is service-related, diagnostic, usage, and performance information our servers automatically collect when you access or use our Services and which we record in log files. Depending on how you interact with us, this log data may include your IP address, device information, browser type, and settings and information about your activity in the Services (such as the date/time stamps associated with your usage, pages and files viewed, searches, and other actions you take such as which features you use), device event information (such as system activity, error reports (sometimes called "crash dumps"), and hardware settings).
<br />
**2. HOW DO WE PROCESS YOUR INFORMATION?**
<br />
In Short: We process your information to provide, improve, and administer our Services, communicate with you, for security and fraud prevention, and to comply with law. We may also process your information for other purposes with your consent.
<br />
We process your personal information for a variety of reasons, depending on how you interact with our Services, including:
<br />
To save or protect an individual's vital interest. We may process your information when necessary to save or protect an individuals vital interest, such as to prevent harm.
<br />
**3. WHAT LEGAL BASES DO WE RELY ON TO PROCESS YOUR INFORMATION?**
<br />
In Short: We only process your personal information when we believe it is necessary and we have a valid legal reason (i.e., legal basis) to do so under applicable law, like with your consent, to comply with laws, to provide you with services to enter into or fulfill our contractual obligations, to protect your rights, or to fulfill our legitimate business interests.
<br />
If you are located in the EU or UK, this section applies to you.
The General Data Protection Regulation (GDPR) and UK GDPR require us to explain the valid legal bases we rely on in order to process your personal information. As such, we may rely on the following legal bases to process your personal information:
Consent. We may process your information if you have given us permission (i.e., consent) to use your personal information for a specific purpose. You can withdraw your consent at any time. Click here to learn more.
Legal Obligations. We may process your information where we believe it is necessary for compliance with our legal obligations, such as to cooperate with a law enforcement body or regulatory agency, exercise or defend our legal rights, or disclose your information as evidence in litigation in which we are involved.
Vital Interests. We may process your information where we believe it is necessary to protect your vital interests or the vital interests of a third party, such as situations involving potential threats to the safety of any person.
<br />
If you are located in Canada, this section applies to you.
We may process your information if you have given us specific permission (i.e., express consent) to use your personal information for a specific purpose, or in situations where your permission can be inferred (i.e., implied consent). You can withdraw your consent at any time. Click here to learn more.
<br />
In some exceptional cases, we may be legally permitted under applicable law to process your information without your consent, including, for example:
If collection is clearly in the interests of an individual and consent cannot be obtained in a timely way
For investigations and fraud detection and prevention
For business transactions provided certain conditions are met
If it is contained in a witness statement and the collection is necessary to assess, process, or settle an insurance claim
For identifying injured, ill, or deceased persons and communicating with next of kin
If we have reasonable grounds to believe an individual has been, is, or may be victim of financial abuse
If it is reasonable to expect collection and use with consent would compromise the availability or the accuracy of the information and the collection is reasonable for purposes related to investigating a breach of an agreement or a contravention of the laws of Canada or a province
If disclosure is required to comply with a subpoena, warrant, court order, or rules of the court relating to the production of records
If it was produced by an individual in the course of their employment, business, or profession and the collection is consistent with the purposes for which the information was produced
If the collection is solely for journalistic, artistic, or literary purposes
If the information is publicly available and is specified by the regulations
<br />
**4. WHEN AND WITH WHOM DO WE SHARE YOUR PERSONAL INFORMATION?**
<br />
In Short: We may share information in specific situations described in this section and/or with the following third parties.
<br />
We may need to share your personal information in the following situations:
Business Transfers. We may share or transfer your information in connection with, or during negotiations of, any merger, sale of company assets, financing, or acquisition of all or a portion of our business to another company.
<br />
**5. DO WE USE COOKIES AND OTHER TRACKING TECHNOLOGIES?**
In Short: We may use cookies and other tracking technologies to collect and store your information.
<br />
We may use cookies and similar tracking technologies (like web beacons and pixels) to access or store information. Specific information about how we use such technologies and how you can refuse certain cookies is set out in our Cookie Notice.
<br />
**6. HOW LONG DO WE KEEP YOUR INFORMATION?**
<br />
In Short: We keep your information for as long as necessary to fulfill the purposes outlined in this privacy notice unless otherwise required by law.
<br />
We will only keep your personal information for as long as it is necessary for the purposes set out in this privacy notice, unless a longer retention period is required or permitted by law (such as tax, accounting, or other legal requirements). No purpose in this notice will require us keeping your personal information for longer than 2 years.
<br />
When we have no ongoing legitimate business need to process your personal information, we will either delete or anonymize such information, or, if this is not possible (for example, because your personal information has been stored in backup archives), then we will securely store your personal information and isolate it from any further processing until deletion is possible.
<br />
**7. HOW DO WE KEEP YOUR INFORMATION SAFE?**
<br />
In Short: We aim to protect your personal information through a system of organizational and technical security measures.
<br />
We have implemented appropriate and reasonable technical and organizational security measures designed to protect the security of any personal information we process. However, despite our safeguards and efforts to secure your information, no electronic transmission over the Internet or information storage technology can be guaranteed to be 100% secure, so we cannot promise or guarantee that hackers, cybercriminals, or other unauthorized third parties will not be able to defeat our security and improperly collect, access, steal, or modify your information. Although we will do our best to protect your personal information, transmission of personal information to and from our Services is at your own risk. You should only access the Services within a secure environment.
<br />
**8. WHAT ARE YOUR PRIVACY RIGHTS?**
<br />
In Short: In some regions, such as the European Economic Area (EEA), United Kingdom (UK), and Canada, you have rights that allow you greater access to and control over your personal information. You may review, change, or terminate your account at any time.
<br />
In some regions (like the EEA, UK, and Canada), you have certain rights under applicable data protection laws. These may include the right (i) to request access and obtain a copy of your personal information, (ii) to request rectification or erasure; (iii) to restrict the processing of your personal information; and (iv) if applicable, to data portability. In certain circumstances, you may also have the right to object to the processing of your personal information. You can make such a request by contacting us by using the contact details provided in the section "HOW CAN YOU CONTACT US ABOUT THIS NOTICE?" below.
<br />
We will consider and act upon any request in accordance with applicable data protection laws.
<br />
If you are located in the EEA or UK and you believe we are unlawfully processing your personal information, you also have the right to complain to your local data protection supervisory authority. You can find their contact details here: https://ec.europa.eu/justice/data-protection/bodies/authorities/index_en.htm.
<br />
If you are located in Switzerland, the contact details for the data protection authorities are available here: https://www.edoeb.admin.ch/edoeb/en/home.html.
<br />
Withdrawing your consent: If we are relying on your consent to process your personal information, which may be express and/or implied consent depending on the applicable law, you have the right to withdraw your consent at any time. You can withdraw your consent at any time by contacting us by using the contact details provided in the section "HOW CAN YOU CONTACT US ABOUT THIS NOTICE?" below.
<br />
However, please note that this will not affect the lawfulness of the processing before its withdrawal, nor when applicable law allows, will it affect the processing of your personal information conducted in reliance on lawful processing grounds other than consent.
<br />
Cookies and similar technologies: Most Web browsers are set to accept cookies by default. If you prefer, you can usually choose to set your browser to remove cookies and to reject cookies. If you choose to remove cookies or reject cookies, this could affect certain features or services of our Services. To opt out of interest-based advertising by advertisers on our Services visit http://www.aboutads.info/choices/.
<br />
If you have questions or comments about your privacy rights, you may email us at hello@jsonhero.io.
<br />
**9. CONTROLS FOR DO-NOT-TRACK FEATURES**
<br />
Most web browsers and some mobile operating systems and mobile applications include a Do-Not-Track ("DNT") feature or setting you can activate to signal your privacy preference not to have data about your online browsing activities monitored and collected. At this stage no uniform technology standard for recognizing and implementing DNT signals has been finalized. As such, we do not currently respond to DNT browser signals or any other mechanism that automatically communicates your choice not to be tracked online. If a standard for online tracking is adopted that we must follow in the future, we will inform you about that practice in a revised version of this privacy notice.
<br />
**10. DO CALIFORNIA RESIDENTS HAVE SPECIFIC PRIVACY RIGHTS?**
<br />
In Short: Yes, if you are a resident of California, you are granted specific rights regarding access to your personal information.
<br />
California Civil Code Section 1798.83, also known as the "Shine The Light" law, permits our users who are California residents to request and obtain from us, once a year and free of charge, information about categories of personal information (if any) we disclosed to third parties for direct marketing purposes and the names and addresses of all third parties with which we shared personal information in the immediately preceding calendar year. If you are a California resident and would like to make such a request, please submit your request in writing to us using the contact information provided below.
<br />
If you are under 18 years of age, reside in California, and have a registered account with Services, you have the right to request removal of unwanted data that you publicly post on the Services. To request removal of such data, please contact us using the contact information provided below and include the email address associated with your account and a statement that you reside in California. We will make sure the data is not publicly displayed on the Services, but please be aware that the data may not be completely or comprehensively removed from all our systems (e.g., backups, etc.).
<br />
**11. DO WE MAKE UPDATES TO THIS NOTICE?**
<br />
In Short: Yes, we will update this notice as necessary to stay compliant with relevant laws.
<br />
We may update this privacy notice from time to time. The updated version will be indicated by an updated "Revised" date and the updated version will be effective as soon as it is accessible. If we make material changes to this privacy notice, we may notify you either by prominently posting a notice of such changes or by directly sending you a notification. We encourage you to review this privacy notice frequently to be informed of how we are protecting your information.
<br />
**12. HOW CAN YOU CONTACT US ABOUT THIS NOTICE?**
<br />
If you have questions or comments about this notice, you may email us at hello@jsonhero.io or by post to:
<br />
Stack Hero Limited
68 Hanbury St
London, England E1 5JL
United Kingdom
<br />
**13. HOW CAN YOU REVIEW, UPDATE, OR DELETE THE DATA WE COLLECT FROM YOU?**
<br />
Based on the applicable laws of your country, you may have the right to request access to the personal information we collect from you, change that information, or delete it in some circumstances. To request to review, update, or delete your personal information, please visit: hello@jsonhero.io.
</div>
+39 -5
View File
@@ -37,7 +37,11 @@ async function getPeekalink(link: string): Promise<PreviewResult> {
}
export async function getUriPreview(uri: string): Promise<PreviewResult> {
const head = await headUri(uri);
console.log(`[getPreview][getUriPreview] ${uri}`);
const url = rewriteUrl(uri);
const head = await headUri(url.href);
// If the url is an image content type, return a preview image
if (
@@ -46,14 +50,14 @@ export async function getUriPreview(uri: string): Promise<PreviewResult> {
contentType.includes(head.contentType)
)
) {
const previewImage = createPreviewImage(uri, head);
const previewImage = createPreviewImage(url.href, head);
return previewImage;
}
// If the url is a json content type, attempt to request the json and return a preview json
if (head?.contentType.includes("application/json")) {
const response = await safeFetch(uri, {
const response = await safeFetch(url.href, {
headers: {
accept: "application/json",
},
@@ -65,10 +69,10 @@ export async function getUriPreview(uri: string): Promise<PreviewResult> {
const jsonBody = await response.json();
return createPreviewJson(uri, jsonBody);
return createPreviewJson(url.href, jsonBody);
}
const peekalinkResult = await getPeekalink(uri);
const peekalinkResult = await getPeekalink(url.href);
return peekalinkResult;
}
@@ -149,3 +153,33 @@ function createPreviewImage(uri: string, head: HeadInfo): PreviewImage {
size: head.contentLength,
};
}
// Rewrites the URL to convert an ipfs: url to use https://ipfs.io/ipfs/
function rewriteUrl(url: string): URL {
const unmodifiedUrl = new URL(url);
console.log(
`[getPreview][rewriteUrl] ${unmodifiedUrl.href}, protocol: ${unmodifiedUrl.protocol}, hostname: ${unmodifiedUrl.hostname}, pathname: ${unmodifiedUrl.pathname}, search: ${unmodifiedUrl.search}, hash: ${unmodifiedUrl.hash}`
);
// Rewrite the URL if it is a relative URL
if (unmodifiedUrl.protocol === "ipfs:") {
if (unmodifiedUrl.hostname === "") {
return new URL(
`https://ipfs.io/ipfs/${unmodifiedUrl.pathname.substring(2)}`
);
} else {
// Parse out the "hostname" from the raw url because hostnames are case-insensitive and automatically lowercased
const urlMatches = url.match(/^ipfs:\/\/([A-Za-z0-9]+)(\/.*)?/i);
const hostname = urlMatches?.[1];
return new URL(
`https://ipfs.io/ipfs/${hostname ?? unmodifiedUrl.hostname}${
unmodifiedUrl.pathname.length > 0 ? `/${unmodifiedUrl.pathname}` : ""
}${unmodifiedUrl.search}`
);
}
}
return unmodifiedUrl;
}
+6
View File
@@ -28,6 +28,10 @@ export function groupRelatedValues(
return "undefined";
} else if (value == null) {
return "null";
} else if (Array.isArray(value)) {
return "[...]";
} else if (typeof value === "object") {
return "{...}";
} else {
return value.toString();
}
@@ -71,6 +75,8 @@ export function getRelatedPathsAtPath(
if (inferredType.name !== "array") continue;
if (index + 1 === pathDepth) continue;
for (
let childIndex = 0;
childIndex < inferredType.value.length;
+229 -216
View File
@@ -53,10 +53,11 @@
"@types/lodash-es": "^4.17.6",
"@types/react": "^17.0.24",
"@types/react-dom": "^17.0.9",
"@types/ua-parser-js": "^0.7.36",
"concurrently": "^7.0.0",
"esbuild-visualizer": "^0.3.1",
"jest": "^27.4.7",
"miniflare": "^2.1.0",
"miniflare": "^2.4.0",
"patch-package": "^6.4.7",
"rimraf": "^3.0.2",
"tailwindcss": "^3.0.22",
@@ -1724,9 +1725,9 @@
}
},
"node_modules/@jsonhero/json-infer-types": {
"version": "1.2.9",
"resolved": "https://registry.npmjs.org/@jsonhero/json-infer-types/-/json-infer-types-1.2.9.tgz",
"integrity": "sha512-QuIOEy7M57bB4fhwadtDUQv5HjrUFD9SXjvQfWUMSQ6zOL8l9S9SV/wRQCn0y0dal+xZPBoMoDqTMJyEBIHnQQ==",
"version": "1.2.10",
"resolved": "https://registry.npmjs.org/@jsonhero/json-infer-types/-/json-infer-types-1.2.10.tgz",
"integrity": "sha512-D91mdtH59U76CRflPZrRfkPMuUPQjBaCqDpH18WnSC0tTqLKymF11XAGcY0KLeXoFd2EqJu9Q8HwxsFOTQQa8A==",
"dependencies": {
"ip-address": "^8.1.0",
"json5": "^2.2.0",
@@ -1793,13 +1794,13 @@
}
},
"node_modules/@miniflare/cache": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.3.0.tgz",
"integrity": "sha512-lOf3WVtrs0ac7KOtsQ+JOGHWR90zsqqJbolE+Wt4hIZuvM2U3t1RD2Ms7U20J301msVIsBAd02IL57H95LXQtQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.4.0.tgz",
"integrity": "sha512-tMDXlUVlThgFubJmlxZoKmLK8kBxDmuMbVMt7csHpXegzkuo2TmIsDqBE/C3CRiJ5xeCQgpD6iZtKBu5Zn5fRA==",
"dev": true,
"dependencies": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"http-cache-semantics": "^4.1.0",
"undici": "4.13.0"
},
@@ -1808,12 +1809,12 @@
}
},
"node_modules/@miniflare/cli-parser": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.3.0.tgz",
"integrity": "sha512-yQzU+OBBvWshr9qVxAe6bWXJLNfpmLYrfkfR3u+rPOo2LYnccWg0f/8jtxrXM1TIyu+tCOJGqCODpO//XtrwWw==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.4.0.tgz",
"integrity": "sha512-Xr5lO8f+oIr9r/b2dfo0on1p0MNN+pkwRHWoY5ACSnp9FaGnwm/g71DM7AajIQPIk0TpRsSVNDx8Ygj1LPT+sQ==",
"dev": true,
"dependencies": {
"@miniflare/shared": "2.3.0",
"@miniflare/shared": "2.4.0",
"kleur": "^4.1.4"
},
"engines": {
@@ -1821,14 +1822,14 @@
}
},
"node_modules/@miniflare/core": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.3.0.tgz",
"integrity": "sha512-Dltb3p+Uq5Lx53DuInckHYaDoMrBq49HE/p/oUDXmzHmQy7EAM6v+nJGKmiM9Uen4OqyqsmlmPWqntSMjaX7Jg==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.4.0.tgz",
"integrity": "sha512-vYl8xaWTFzxtkbzx3IkT4Py0OAFdfmFnVo627O1HKHWVGlkjVr8UKtxBpIR+f5pq/HCMzzqA1HM9FXO0dQfy3A==",
"dev": true,
"dependencies": {
"@iarna/toml": "^2.2.5",
"@miniflare/shared": "2.3.0",
"@miniflare/watcher": "2.3.0",
"@miniflare/shared": "2.4.0",
"@miniflare/watcher": "2.4.0",
"busboy": "^0.3.1",
"dotenv": "^10.0.0",
"kleur": "^4.1.4",
@@ -1840,14 +1841,14 @@
}
},
"node_modules/@miniflare/durable-objects": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.3.0.tgz",
"integrity": "sha512-YuzxBBu9xBU3xxD4TzGdeVVMXrE76AWJE4MIqkJR5UmASqayyv//cApGw3+C01NHe07cpbrTM1QTgFo2eBncwQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.4.0.tgz",
"integrity": "sha512-VVLaUXXcAQcYE/3YmDLTacZf5OzR8bib6q1T9NqVb0uK5sLMQqyHvQdsG5rMqs7iyxfJxyZ0bL2OW9XGALOkoQ==",
"dev": true,
"dependencies": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/storage-memory": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"@miniflare/storage-memory": "2.4.0",
"undici": "4.13.0"
},
"engines": {
@@ -1855,13 +1856,13 @@
}
},
"node_modules/@miniflare/html-rewriter": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.3.0.tgz",
"integrity": "sha512-cyWhmQgzhtRlBeg0mxP5FmAq/75ChuLwWQlhokx88XkGnteuh0/DOk3OxIMaveF2oDHKmIlLFgSlzv4NbT1Mng==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.4.0.tgz",
"integrity": "sha512-ZG8819N7LelDD+8+Ss5FZpVyQQq/V2igod0qE68JK4he/w4/yn57Rk6Efb49y15HoHAXl2RpCCsnCyIow/Xjug==",
"dev": true,
"dependencies": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"html-rewriter-wasm": "^0.4.1",
"undici": "4.13.0"
},
@@ -1870,14 +1871,14 @@
}
},
"node_modules/@miniflare/http-server": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.3.0.tgz",
"integrity": "sha512-jTzsRuro3yWVb4T85znBGw1w+ydimgi2PJvHrTuGFKDjFam+R037fGH+HZCAjAgPiBHTroXfkeSXypJLXbQBEg==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.4.0.tgz",
"integrity": "sha512-r6Z/nqxE0oa1z63L95yvnG0PUeLRxZOeGS7ADxZMFKan4WD5lvYtSKDuDEm0lkbQshCOHQ3uXFr0cotOm8JoMQ==",
"dev": true,
"dependencies": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/web-sockets": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"@miniflare/web-sockets": "2.4.0",
"kleur": "^4.1.4",
"selfsigned": "^2.0.0",
"undici": "4.13.0",
@@ -1889,9 +1890,9 @@
}
},
"node_modules/@miniflare/http-server/node_modules/ws": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
"dev": true,
"engines": {
"node": ">=10.0.0"
@@ -1910,37 +1911,37 @@
}
},
"node_modules/@miniflare/kv": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.3.0.tgz",
"integrity": "sha512-m0zu5sRoaFDm+WVTnLRrz8+77b6eVxQN7cLN6ZQiKP3Nd8cAggPdaIIef8dVksWbPvOW9DztoUVZTB1v9EOaLA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.4.0.tgz",
"integrity": "sha512-1UW7f1386xR6EDEXNZOR1TpFwQfRRSxUPqD6m/U0WprlsbM0cIYGz+AUeaVbkFf8lfE2MeXCUrjbWsLOvsnw3g==",
"dev": true,
"dependencies": {
"@miniflare/shared": "2.3.0"
"@miniflare/shared": "2.4.0"
},
"engines": {
"node": ">=16.7"
}
},
"node_modules/@miniflare/runner-vm": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.3.0.tgz",
"integrity": "sha512-/aB997YodNcRFxtlnvEn4BJSIqKXRw29FexOqCWwWv+b7XQkTTxd4IfSocIFi6du3265gp85icqP/hxsLAQBVg==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.4.0.tgz",
"integrity": "sha512-7sdwBYzXQTwYeR3tTvQ+vJfzc7BXwqR8AUPK9l5gvCtg+Geq9sMslr5SikIJpgcvbYqKDjvC9DQEPJ3sqr9cSQ==",
"dev": true,
"dependencies": {
"@miniflare/shared": "2.3.0"
"@miniflare/shared": "2.4.0"
},
"engines": {
"node": ">=16.7"
}
},
"node_modules/@miniflare/scheduler": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.3.0.tgz",
"integrity": "sha512-Er80srMNXbxqGbYXtiZkD8UlveHsw4cpwcytQgsEJCHG7/48vC/rpmtN0zKOWFEHifaOUvHhURZRJu+S2E4Stg==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.4.0.tgz",
"integrity": "sha512-dfMCXoAS8Y+3xABNxYju62I2xIBS54Op7ohCHoatvAM5RvualJUPICEMPZzX6/z29q5xPIeSLhLDhl/asAQ19w==",
"dev": true,
"dependencies": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"cron-schedule": "^3.0.4"
},
"engines": {
@@ -1948,9 +1949,9 @@
}
},
"node_modules/@miniflare/shared": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.3.0.tgz",
"integrity": "sha512-TvCSUe1op5AKINx3zHSSdfAbdoV3eSF3MzeVQA4+1NmtuefY8cjujQCdILeAxg3oPbHXaZkc7j1zZ13rYdvwGQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.4.0.tgz",
"integrity": "sha512-lPQFzBUVGNQ93gQ/dliToWnO0OqAgsD3/902Pd/IixVSRwRj3BTnYv2dHMUKZcODBPrhnbqZeqcPWdBLzEx8uw==",
"dev": true,
"dependencies": {
"ignore": "^5.1.8",
@@ -1961,64 +1962,64 @@
}
},
"node_modules/@miniflare/sites": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.3.0.tgz",
"integrity": "sha512-WkRBxQbf6k/eS1D/D1mw30Zs253TFeIkWFh8HQ8Z36Kdt79rNVezT9YmRpahUfvYXmubTquV5JftNOAhvbOJXA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.4.0.tgz",
"integrity": "sha512-YZy/TujnR1lkBvCncDDQ8tsWsXRE4JJ4x9a0bKN/XnZh7r6OhDM0sw4BFcBQhT6Ukdtttam1O3FlJxnMitrDGg==",
"dev": true,
"dependencies": {
"@miniflare/kv": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/storage-file": "2.3.0"
"@miniflare/kv": "2.4.0",
"@miniflare/shared": "2.4.0",
"@miniflare/storage-file": "2.4.0"
},
"engines": {
"node": ">=16.7"
}
},
"node_modules/@miniflare/storage-file": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.3.0.tgz",
"integrity": "sha512-1rda/MC0R8wVC6N7Na2EdSGNAZv6o/yugp7Z+GikJ1vbgi1+9soAczDzFtaq4jrBzAkCFOMT79DgkSKSl59vxg==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.4.0.tgz",
"integrity": "sha512-f1AUMz8xps/4VhNJMb8JeCevZFeU4pg2lIWmC11gG4xeq2nibTPBi6Qtx594Le7ZKij/tF6rRsoNfGau2Q5gdw==",
"dev": true,
"dependencies": {
"@miniflare/shared": "2.3.0",
"@miniflare/storage-memory": "2.3.0"
"@miniflare/shared": "2.4.0",
"@miniflare/storage-memory": "2.4.0"
},
"engines": {
"node": ">=16.7"
}
},
"node_modules/@miniflare/storage-memory": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.3.0.tgz",
"integrity": "sha512-cMqQK9neRySchoNUVhQYOmLFrYkAjT5V113Wfxmsz93dladQ1/mXOsndqPrlb+5hhnwbw4Ns67nyzkHUe9sX/g==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.4.0.tgz",
"integrity": "sha512-mhWwgHhDNtEa7y1bYbdVucV0lqUmzagYXUSppAdSGS5JPyJMyw3HseqRNTk6gC/vKlvEYlFf3ugWcREGCedr9A==",
"dev": true,
"dependencies": {
"@miniflare/shared": "2.3.0"
"@miniflare/shared": "2.4.0"
},
"engines": {
"node": ">=16.7"
}
},
"node_modules/@miniflare/watcher": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.3.0.tgz",
"integrity": "sha512-G0ZE9WHIcdR2TlPXwwQabULDIMZ9LujfC0tn+yXmPXKxgWoJWcWFmUbkhVDcOJzkIz2TAhRlLbW11n8nChUHFQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.4.0.tgz",
"integrity": "sha512-gDQRUxwOjmctvowyd4Hcdy3fjxz3ERKzirp6TvA3AWUohKZk3IhwGlaA8aCwbdP+ELYQlG5wK44AfLSGi956fg==",
"dev": true,
"dependencies": {
"@miniflare/shared": "2.3.0"
"@miniflare/shared": "2.4.0"
},
"engines": {
"node": ">=16.7"
}
},
"node_modules/@miniflare/web-sockets": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.3.0.tgz",
"integrity": "sha512-3xcPG1vfiMb2obVC4jNtS5VzUxzM1rdUrWPCG86gpZaHky0xC1U7Tp+eFdxQFTty99HPYrrVKXl1ww2h1LGWRA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.4.0.tgz",
"integrity": "sha512-cz/cN0GoQOXRLh80UmlcEJODPIw2ijKBK3PLRzvfTzqQ5avK6wp2M8Fj8C/5JIT6g7siwvBANyKXD3U3RpKGHQ==",
"dev": true,
"dependencies": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"undici": "4.13.0",
"ws": "^8.2.2"
},
@@ -2027,9 +2028,9 @@
}
},
"node_modules/@miniflare/web-sockets/node_modules/ws": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
"dev": true,
"engines": {
"node": ">=10.0.0"
@@ -3050,6 +3051,12 @@
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
"dev": true
},
"node_modules/@types/ua-parser-js": {
"version": "0.7.36",
"resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz",
"integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==",
"dev": true
},
"node_modules/@types/unist": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
@@ -4396,9 +4403,9 @@
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
},
"node_modules/cron-schedule": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.5.tgz",
"integrity": "sha512-YjtB4jy7RJEX8j9GokHp+y8S/ihCHjrD2Z3E13LSGP/+G0Sdv+MEKsZu5wPLLWwW1HQc4HwpGMFU3GUTStZTaA==",
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.6.tgz",
"integrity": "sha512-izfGgKyzzIyLaeb1EtZ3KbglkS6AKp9cv7LxmiyoOu+fXfol1tQDC0Cof0enVZGNtudTHW+3lfuW9ZkLQss4Wg==",
"dev": true
},
"node_modules/cross-spawn": {
@@ -10236,25 +10243,25 @@
}
},
"node_modules/miniflare": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.3.0.tgz",
"integrity": "sha512-0lK4Df+jfqLDSDDgj4AOJffb1G6sN7XvB5QGUaquEakW+qPdurydyNhFKcFKBgpk4ozN6WTmB2x802iPXQcJJQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.4.0.tgz",
"integrity": "sha512-xOBL/dQsUL95rxIYO+KrrVPPpm2TAf6TKl4AvhcjSfUeVkzDWd/y9f7hXCt8x6srDoK0Z2LpYouatvSfSUzGOw==",
"dev": true,
"dependencies": {
"@miniflare/cache": "2.3.0",
"@miniflare/cli-parser": "2.3.0",
"@miniflare/core": "2.3.0",
"@miniflare/durable-objects": "2.3.0",
"@miniflare/html-rewriter": "2.3.0",
"@miniflare/http-server": "2.3.0",
"@miniflare/kv": "2.3.0",
"@miniflare/runner-vm": "2.3.0",
"@miniflare/scheduler": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/sites": "2.3.0",
"@miniflare/storage-file": "2.3.0",
"@miniflare/storage-memory": "2.3.0",
"@miniflare/web-sockets": "2.3.0",
"@miniflare/cache": "2.4.0",
"@miniflare/cli-parser": "2.4.0",
"@miniflare/core": "2.4.0",
"@miniflare/durable-objects": "2.4.0",
"@miniflare/html-rewriter": "2.4.0",
"@miniflare/http-server": "2.4.0",
"@miniflare/kv": "2.4.0",
"@miniflare/runner-vm": "2.4.0",
"@miniflare/scheduler": "2.4.0",
"@miniflare/shared": "2.4.0",
"@miniflare/sites": "2.4.0",
"@miniflare/storage-file": "2.4.0",
"@miniflare/storage-memory": "2.4.0",
"@miniflare/web-sockets": "2.4.0",
"kleur": "^4.1.4",
"semiver": "^1.1.0",
"source-map-support": "^0.5.20",
@@ -10267,7 +10274,7 @@
"node": ">=16.7"
},
"peerDependencies": {
"@miniflare/storage-redis": "2.3.0",
"@miniflare/storage-redis": "2.4.0",
"cron-schedule": "^3.0.4",
"ioredis": "^4.27.9"
},
@@ -10491,9 +10498,9 @@
}
},
"node_modules/node-forge": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
"dev": true,
"engines": {
"node": ">= 6.13.0"
@@ -11919,12 +11926,12 @@
}
},
"node_modules/selfsigned": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz",
"integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz",
"integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==",
"dev": true,
"dependencies": {
"node-forge": "^1.2.0"
"node-forge": "^1"
},
"engines": {
"node": ">=10"
@@ -14905,9 +14912,9 @@
}
},
"@jsonhero/json-infer-types": {
"version": "1.2.9",
"resolved": "https://registry.npmjs.org/@jsonhero/json-infer-types/-/json-infer-types-1.2.9.tgz",
"integrity": "sha512-QuIOEy7M57bB4fhwadtDUQv5HjrUFD9SXjvQfWUMSQ6zOL8l9S9SV/wRQCn0y0dal+xZPBoMoDqTMJyEBIHnQQ==",
"version": "1.2.10",
"resolved": "https://registry.npmjs.org/@jsonhero/json-infer-types/-/json-infer-types-1.2.10.tgz",
"integrity": "sha512-D91mdtH59U76CRflPZrRfkPMuUPQjBaCqDpH18WnSC0tTqLKymF11XAGcY0KLeXoFd2EqJu9Q8HwxsFOTQQa8A==",
"requires": {
"ip-address": "^8.1.0",
"json5": "^2.2.0",
@@ -14962,36 +14969,36 @@
}
},
"@miniflare/cache": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.3.0.tgz",
"integrity": "sha512-lOf3WVtrs0ac7KOtsQ+JOGHWR90zsqqJbolE+Wt4hIZuvM2U3t1RD2Ms7U20J301msVIsBAd02IL57H95LXQtQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.4.0.tgz",
"integrity": "sha512-tMDXlUVlThgFubJmlxZoKmLK8kBxDmuMbVMt7csHpXegzkuo2TmIsDqBE/C3CRiJ5xeCQgpD6iZtKBu5Zn5fRA==",
"dev": true,
"requires": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"http-cache-semantics": "^4.1.0",
"undici": "4.13.0"
}
},
"@miniflare/cli-parser": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.3.0.tgz",
"integrity": "sha512-yQzU+OBBvWshr9qVxAe6bWXJLNfpmLYrfkfR3u+rPOo2LYnccWg0f/8jtxrXM1TIyu+tCOJGqCODpO//XtrwWw==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.4.0.tgz",
"integrity": "sha512-Xr5lO8f+oIr9r/b2dfo0on1p0MNN+pkwRHWoY5ACSnp9FaGnwm/g71DM7AajIQPIk0TpRsSVNDx8Ygj1LPT+sQ==",
"dev": true,
"requires": {
"@miniflare/shared": "2.3.0",
"@miniflare/shared": "2.4.0",
"kleur": "^4.1.4"
}
},
"@miniflare/core": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.3.0.tgz",
"integrity": "sha512-Dltb3p+Uq5Lx53DuInckHYaDoMrBq49HE/p/oUDXmzHmQy7EAM6v+nJGKmiM9Uen4OqyqsmlmPWqntSMjaX7Jg==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.4.0.tgz",
"integrity": "sha512-vYl8xaWTFzxtkbzx3IkT4Py0OAFdfmFnVo627O1HKHWVGlkjVr8UKtxBpIR+f5pq/HCMzzqA1HM9FXO0dQfy3A==",
"dev": true,
"requires": {
"@iarna/toml": "^2.2.5",
"@miniflare/shared": "2.3.0",
"@miniflare/watcher": "2.3.0",
"@miniflare/shared": "2.4.0",
"@miniflare/watcher": "2.4.0",
"busboy": "^0.3.1",
"dotenv": "^10.0.0",
"kleur": "^4.1.4",
@@ -15000,38 +15007,38 @@
}
},
"@miniflare/durable-objects": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.3.0.tgz",
"integrity": "sha512-YuzxBBu9xBU3xxD4TzGdeVVMXrE76AWJE4MIqkJR5UmASqayyv//cApGw3+C01NHe07cpbrTM1QTgFo2eBncwQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.4.0.tgz",
"integrity": "sha512-VVLaUXXcAQcYE/3YmDLTacZf5OzR8bib6q1T9NqVb0uK5sLMQqyHvQdsG5rMqs7iyxfJxyZ0bL2OW9XGALOkoQ==",
"dev": true,
"requires": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/storage-memory": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"@miniflare/storage-memory": "2.4.0",
"undici": "4.13.0"
}
},
"@miniflare/html-rewriter": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.3.0.tgz",
"integrity": "sha512-cyWhmQgzhtRlBeg0mxP5FmAq/75ChuLwWQlhokx88XkGnteuh0/DOk3OxIMaveF2oDHKmIlLFgSlzv4NbT1Mng==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.4.0.tgz",
"integrity": "sha512-ZG8819N7LelDD+8+Ss5FZpVyQQq/V2igod0qE68JK4he/w4/yn57Rk6Efb49y15HoHAXl2RpCCsnCyIow/Xjug==",
"dev": true,
"requires": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"html-rewriter-wasm": "^0.4.1",
"undici": "4.13.0"
}
},
"@miniflare/http-server": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.3.0.tgz",
"integrity": "sha512-jTzsRuro3yWVb4T85znBGw1w+ydimgi2PJvHrTuGFKDjFam+R037fGH+HZCAjAgPiBHTroXfkeSXypJLXbQBEg==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.4.0.tgz",
"integrity": "sha512-r6Z/nqxE0oa1z63L95yvnG0PUeLRxZOeGS7ADxZMFKan4WD5lvYtSKDuDEm0lkbQshCOHQ3uXFr0cotOm8JoMQ==",
"dev": true,
"requires": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/web-sockets": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"@miniflare/web-sockets": "2.4.0",
"kleur": "^4.1.4",
"selfsigned": "^2.0.0",
"undici": "4.13.0",
@@ -15040,47 +15047,47 @@
},
"dependencies": {
"ws": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
"dev": true,
"requires": {}
}
}
},
"@miniflare/kv": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.3.0.tgz",
"integrity": "sha512-m0zu5sRoaFDm+WVTnLRrz8+77b6eVxQN7cLN6ZQiKP3Nd8cAggPdaIIef8dVksWbPvOW9DztoUVZTB1v9EOaLA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.4.0.tgz",
"integrity": "sha512-1UW7f1386xR6EDEXNZOR1TpFwQfRRSxUPqD6m/U0WprlsbM0cIYGz+AUeaVbkFf8lfE2MeXCUrjbWsLOvsnw3g==",
"dev": true,
"requires": {
"@miniflare/shared": "2.3.0"
"@miniflare/shared": "2.4.0"
}
},
"@miniflare/runner-vm": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.3.0.tgz",
"integrity": "sha512-/aB997YodNcRFxtlnvEn4BJSIqKXRw29FexOqCWwWv+b7XQkTTxd4IfSocIFi6du3265gp85icqP/hxsLAQBVg==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.4.0.tgz",
"integrity": "sha512-7sdwBYzXQTwYeR3tTvQ+vJfzc7BXwqR8AUPK9l5gvCtg+Geq9sMslr5SikIJpgcvbYqKDjvC9DQEPJ3sqr9cSQ==",
"dev": true,
"requires": {
"@miniflare/shared": "2.3.0"
"@miniflare/shared": "2.4.0"
}
},
"@miniflare/scheduler": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.3.0.tgz",
"integrity": "sha512-Er80srMNXbxqGbYXtiZkD8UlveHsw4cpwcytQgsEJCHG7/48vC/rpmtN0zKOWFEHifaOUvHhURZRJu+S2E4Stg==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.4.0.tgz",
"integrity": "sha512-dfMCXoAS8Y+3xABNxYju62I2xIBS54Op7ohCHoatvAM5RvualJUPICEMPZzX6/z29q5xPIeSLhLDhl/asAQ19w==",
"dev": true,
"requires": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"cron-schedule": "^3.0.4"
}
},
"@miniflare/shared": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.3.0.tgz",
"integrity": "sha512-TvCSUe1op5AKINx3zHSSdfAbdoV3eSF3MzeVQA4+1NmtuefY8cjujQCdILeAxg3oPbHXaZkc7j1zZ13rYdvwGQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.4.0.tgz",
"integrity": "sha512-lPQFzBUVGNQ93gQ/dliToWnO0OqAgsD3/902Pd/IixVSRwRj3BTnYv2dHMUKZcODBPrhnbqZeqcPWdBLzEx8uw==",
"dev": true,
"requires": {
"ignore": "^5.1.8",
@@ -15088,60 +15095,60 @@
}
},
"@miniflare/sites": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.3.0.tgz",
"integrity": "sha512-WkRBxQbf6k/eS1D/D1mw30Zs253TFeIkWFh8HQ8Z36Kdt79rNVezT9YmRpahUfvYXmubTquV5JftNOAhvbOJXA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.4.0.tgz",
"integrity": "sha512-YZy/TujnR1lkBvCncDDQ8tsWsXRE4JJ4x9a0bKN/XnZh7r6OhDM0sw4BFcBQhT6Ukdtttam1O3FlJxnMitrDGg==",
"dev": true,
"requires": {
"@miniflare/kv": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/storage-file": "2.3.0"
"@miniflare/kv": "2.4.0",
"@miniflare/shared": "2.4.0",
"@miniflare/storage-file": "2.4.0"
}
},
"@miniflare/storage-file": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.3.0.tgz",
"integrity": "sha512-1rda/MC0R8wVC6N7Na2EdSGNAZv6o/yugp7Z+GikJ1vbgi1+9soAczDzFtaq4jrBzAkCFOMT79DgkSKSl59vxg==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.4.0.tgz",
"integrity": "sha512-f1AUMz8xps/4VhNJMb8JeCevZFeU4pg2lIWmC11gG4xeq2nibTPBi6Qtx594Le7ZKij/tF6rRsoNfGau2Q5gdw==",
"dev": true,
"requires": {
"@miniflare/shared": "2.3.0",
"@miniflare/storage-memory": "2.3.0"
"@miniflare/shared": "2.4.0",
"@miniflare/storage-memory": "2.4.0"
}
},
"@miniflare/storage-memory": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.3.0.tgz",
"integrity": "sha512-cMqQK9neRySchoNUVhQYOmLFrYkAjT5V113Wfxmsz93dladQ1/mXOsndqPrlb+5hhnwbw4Ns67nyzkHUe9sX/g==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.4.0.tgz",
"integrity": "sha512-mhWwgHhDNtEa7y1bYbdVucV0lqUmzagYXUSppAdSGS5JPyJMyw3HseqRNTk6gC/vKlvEYlFf3ugWcREGCedr9A==",
"dev": true,
"requires": {
"@miniflare/shared": "2.3.0"
"@miniflare/shared": "2.4.0"
}
},
"@miniflare/watcher": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.3.0.tgz",
"integrity": "sha512-G0ZE9WHIcdR2TlPXwwQabULDIMZ9LujfC0tn+yXmPXKxgWoJWcWFmUbkhVDcOJzkIz2TAhRlLbW11n8nChUHFQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.4.0.tgz",
"integrity": "sha512-gDQRUxwOjmctvowyd4Hcdy3fjxz3ERKzirp6TvA3AWUohKZk3IhwGlaA8aCwbdP+ELYQlG5wK44AfLSGi956fg==",
"dev": true,
"requires": {
"@miniflare/shared": "2.3.0"
"@miniflare/shared": "2.4.0"
}
},
"@miniflare/web-sockets": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.3.0.tgz",
"integrity": "sha512-3xcPG1vfiMb2obVC4jNtS5VzUxzM1rdUrWPCG86gpZaHky0xC1U7Tp+eFdxQFTty99HPYrrVKXl1ww2h1LGWRA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.4.0.tgz",
"integrity": "sha512-cz/cN0GoQOXRLh80UmlcEJODPIw2ijKBK3PLRzvfTzqQ5avK6wp2M8Fj8C/5JIT6g7siwvBANyKXD3U3RpKGHQ==",
"dev": true,
"requires": {
"@miniflare/core": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/core": "2.4.0",
"@miniflare/shared": "2.4.0",
"undici": "4.13.0",
"ws": "^8.2.2"
},
"dependencies": {
"ws": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
"integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
"dev": true,
"requires": {}
}
@@ -16018,6 +16025,12 @@
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
"dev": true
},
"@types/ua-parser-js": {
"version": "0.7.36",
"resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz",
"integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==",
"dev": true
},
"@types/unist": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
@@ -17037,9 +17050,9 @@
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
},
"cron-schedule": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.5.tgz",
"integrity": "sha512-YjtB4jy7RJEX8j9GokHp+y8S/ihCHjrD2Z3E13LSGP/+G0Sdv+MEKsZu5wPLLWwW1HQc4HwpGMFU3GUTStZTaA==",
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.6.tgz",
"integrity": "sha512-izfGgKyzzIyLaeb1EtZ3KbglkS6AKp9cv7LxmiyoOu+fXfol1tQDC0Cof0enVZGNtudTHW+3lfuW9ZkLQss4Wg==",
"dev": true
},
"cross-spawn": {
@@ -21188,25 +21201,25 @@
"dev": true
},
"miniflare": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.3.0.tgz",
"integrity": "sha512-0lK4Df+jfqLDSDDgj4AOJffb1G6sN7XvB5QGUaquEakW+qPdurydyNhFKcFKBgpk4ozN6WTmB2x802iPXQcJJQ==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.4.0.tgz",
"integrity": "sha512-xOBL/dQsUL95rxIYO+KrrVPPpm2TAf6TKl4AvhcjSfUeVkzDWd/y9f7hXCt8x6srDoK0Z2LpYouatvSfSUzGOw==",
"dev": true,
"requires": {
"@miniflare/cache": "2.3.0",
"@miniflare/cli-parser": "2.3.0",
"@miniflare/core": "2.3.0",
"@miniflare/durable-objects": "2.3.0",
"@miniflare/html-rewriter": "2.3.0",
"@miniflare/http-server": "2.3.0",
"@miniflare/kv": "2.3.0",
"@miniflare/runner-vm": "2.3.0",
"@miniflare/scheduler": "2.3.0",
"@miniflare/shared": "2.3.0",
"@miniflare/sites": "2.3.0",
"@miniflare/storage-file": "2.3.0",
"@miniflare/storage-memory": "2.3.0",
"@miniflare/web-sockets": "2.3.0",
"@miniflare/cache": "2.4.0",
"@miniflare/cli-parser": "2.4.0",
"@miniflare/core": "2.4.0",
"@miniflare/durable-objects": "2.4.0",
"@miniflare/html-rewriter": "2.4.0",
"@miniflare/http-server": "2.4.0",
"@miniflare/kv": "2.4.0",
"@miniflare/runner-vm": "2.4.0",
"@miniflare/scheduler": "2.4.0",
"@miniflare/shared": "2.4.0",
"@miniflare/sites": "2.4.0",
"@miniflare/storage-file": "2.4.0",
"@miniflare/storage-memory": "2.4.0",
"@miniflare/web-sockets": "2.4.0",
"kleur": "^4.1.4",
"semiver": "^1.1.0",
"source-map-support": "^0.5.20",
@@ -21364,9 +21377,9 @@
}
},
"node-forge": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
"dev": true
},
"node-int64": {
@@ -22398,12 +22411,12 @@
}
},
"selfsigned": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz",
"integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz",
"integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==",
"dev": true,
"requires": {
"node-forge": "^1.2.0"
"node-forge": "^1"
}
},
"semiver": {
+2 -1
View File
@@ -73,10 +73,11 @@
"@types/lodash-es": "^4.17.6",
"@types/react": "^17.0.24",
"@types/react-dom": "^17.0.9",
"@types/ua-parser-js": "^0.7.36",
"concurrently": "^7.0.0",
"esbuild-visualizer": "^0.3.1",
"jest": "^27.4.7",
"miniflare": "^2.1.0",
"miniflare": "^2.4.0",
"patch-package": "^6.4.7",
"rimraf": "^3.0.2",
"tailwindcss": "^3.0.22",
+1 -6
View File
@@ -1,9 +1,4 @@
@import url("https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;700;900&display=swap");
@font-face {
font-family: "MonoLisa";
src: url("/fonts/MonoLisa/woff2/MonoLisa-Regular.woff2") format("woff2"),
url("/fonts/MonoLisa/woff/MonoLisa-Regular.woff") format("woff");
}
@import url("https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;700;900&family=Roboto+Mono&display=swap");
@tailwind base;
@tailwind components;
+4 -2
View File
@@ -16,17 +16,19 @@ module.exports = {
"6xl": ["2.625rem", "3rem"], // 42px
"7xl": "4rem", // 64px
"8xl": "8rem", // 128px
},
extend: {
height: {
viewerHeight: "calc(100vh - 146px)",
inspectorHeight: "calc(100vh - 70px)",
jsonViewerHeight: "calc(100vh - 106px)",
viewerHeightMinimal: "calc(100vh - 106px)",
inspectorHeightMinimal: "calc(100vh - 30px)",
jsonViewerHeightMinimal: "calc(100vh - 66px)",
},
fontFamily: {
sans: ["Source Sans Pro", "sans-serif"],
mono: ["MonoLisa", "monospace"],
mono: ["Roboto Mono", "monospace"],
},
},
},
+55 -1
View File
@@ -46,6 +46,9 @@ const json = {
},
id: "B65hEUWW01ErVKDDGImKcBquYhwEAkjW6Ic3lPY0299Cc",
created_at: "1607587513",
another_field: {
nested: "value",
},
modifiedAt: null,
},
{
@@ -75,11 +78,62 @@ const json = {
},
id: "B65hEUWW01ErVKDDGImKcBquYhwEAkjW6Ic3lPY0299Cc",
created_at: "1607587513",
another_field: {
nested: "value",
},
},
],
};
describe("calculateRelatedValuesGroups", () => {
test("it should return the correct values when path is an object", () => {
const path = "$.data.1.another_field";
const result = calculateRelatedValuesGroups(path, json);
expect(result).toMatchInlineSnapshot(`
Array [
Object {
"paths": Array [
"$.data.1.another_field",
"$.data.2.another_field",
],
"value": "{...}",
},
Object {
"paths": Array [
"$.data.0.another_field",
],
"value": "undefined",
},
]
`);
});
test("it should return the correct values when path is an array", () => {
const path = "$.data.1.recent_asset_ids";
const result = calculateRelatedValuesGroups(path, json);
expect(result).toMatchInlineSnapshot(`
Array [
Object {
"paths": Array [
"$.data.1.recent_asset_ids",
"$.data.2.recent_asset_ids",
],
"value": "[...]",
},
Object {
"paths": Array [
"$.data.0.recent_asset_ids",
],
"value": "undefined",
},
]
`);
});
test("it should return the correct related values grouped by value", () => {
const path = "$.data.1.playback_ids.0.policy";
@@ -106,7 +160,7 @@ describe("calculateRelatedValuesGroups", () => {
paths: ["$.data.2.playback_ids.1.policy"],
},
{
value: "[object Object]",
value: "{...}",
paths: ["$.data.2.playback_ids.2.policy"],
},
]);