Author SHA1 Message Date
James Ritchie 6530e71872 Added a Toast component to the app 2022-05-20 11:57:53 +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
Eric Allam d4c23be1b6 Move the examples out of app 2022-05-12 10:08:31 +01:00
James Ritchie 35082d9c43 Small header tweak to fix mobile portrait 2022-05-07 18:33:32 +01:00
D-K-P 48ac6bcdf7 Added Twitter icon to the header / footer of the homepage 2022-05-06 21:13:20 +01:00
James Ritchie 7e46e60d21 Added some example JSON files to help when running locally 2022-05-06 17:12:33 +01:00
Eric Allam 927cc26669 Convert the rest of the samples to ExampleDocs 2022-05-04 21:06:22 +01:00
Eric Allam 401205b57f Convert the Unsplash to the new ExampleDoc 2022-05-04 20:57:00 +01:00
Eric Allam a08fe62e78 Allow url documents to be injested, so it only hits the url once 2022-05-04 20:48:09 +01:00
Eric Allam fdd972b973 Allow creating read-only documents through the /new endpoint with readonly=true (fixes issue #48) 2022-05-03 22:36:27 +01:00
Eric Allam d793753a0a Make sure video element reloads if src changes 2022-05-03 22:05:51 +01:00
Eric Allam 6f548261a1 Adding additional logging to the $id endpoint 2022-05-03 16:39:40 +01:00
Eric Allam 635a97b133 Preview audio & video urls (fixes issue #46) 2022-05-03 15:09:19 +01:00
David Sanchez 3b0a5b80e7 New copy to clipboard shortcut feature and footer icon (#27) 2022-05-03 11:28:30 +01:00
Eric Allam cabd9e3379 Fixed the star count to exactly match github 2022-05-02 21:42:32 +01:00
Eric Allam 436f01e459 Add ttl option to the /new endpoint, allows setting a min 60s timeout 2022-05-02 21:30:19 +01:00
33 changed files with 2155 additions and 411 deletions
+6 -57
View File
@@ -1,36 +1,21 @@
import { Title } from "./Primitives/Title";
import { colorForItemAtPath } from "~/utilities/colors";
import { ColumnViewNode, IconComponent } from "~/useColumnView";
import { IconComponent } from "~/useColumnView";
import { useJson } from "../hooks/useJson";
import { memo, useCallback, useMemo, useRef } from "react";
import { ColumnItem } from "./ColumnItem";
import { useJsonColumnViewAPI } from "~/hooks/useJsonColumnView";
import { useVirtual } from "react-virtual";
import { memo, useMemo } from "react";
export type ColumnProps = {
id: string;
title: string;
icon?: IconComponent;
hasHighlightedElement: boolean;
items: ColumnViewNode[];
selectedPath: string[];
highlightedPath: string[];
children: React.ReactNode;
};
function ColumnElement(column: ColumnProps) {
const { id, title, items, selectedPath, highlightedPath } = column;
const { id, title, children } = column;
const [json] = useJson();
const iconColor = useMemo(() => colorForItemAtPath(id, json), [id, json]);
const { goToNodeId } = useJsonColumnViewAPI();
const containerRef = useRef<HTMLDivElement>(null);
const rowVirtualizer = useVirtual({
size: items.length,
parentRef: containerRef,
estimateSize: useCallback(() => 36, []),
overscan: 5,
});
return (
<div
@@ -42,44 +27,8 @@ function ColumnElement(column: ColumnProps) {
{column.icon && <column.icon className="h-6 w-6 mr-1" />}
<Title className="">{title}</Title>
</div>
<div
className="overflow-y-auto h-viewerHeight no-scrollbar"
ref={containerRef}
>
<div
style={{
height: `${rowVirtualizer.totalSize}px`,
width: "100%",
position: "relative",
}}
>
{rowVirtualizer.virtualItems.map((virtualRow) => {
const item = items[virtualRow.index];
return (
<div
key={virtualRow.index}
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: `${virtualRow.size}px`,
transform: `translateY(${virtualRow.start}px)`,
}}
>
<ColumnItem
item={item}
json={json}
isSelected={selectedPath.includes(item.id)}
isHighlighted={
highlightedPath[highlightedPath.length - 1] === item.id
}
onClick={(id) => goToNodeId(id, "columnView")}
/>
</div>
);
})}
</div>
<div className="overflow-y-auto h-viewerHeight no-scrollbar">
{children}
</div>
</div>
);
+15 -4
View File
@@ -14,6 +14,7 @@ function ColumnsElement({ columns }: { columns: ColumnDefinition[] }) {
const [json] = useJson();
const { selectedPath, highlightedPath, highlightedNodeId } =
useJsonColumnViewState();
const { goToNodeId } = useJsonColumnViewAPI();
const highlightedItemIsValue = useMemo<boolean>(() => {
if (highlightedNodeId == null) {
return false;
@@ -37,10 +38,20 @@ function ColumnsElement({ columns }: { columns: ColumnDefinition[] }) {
hasHighlightedElement={
highlightedPath[highlightedPath.length - 2] === column.id
}
selectedPath={selectedPath}
highlightedPath={highlightedPath}
items={column.items}
/>
>
{column.items.map((item) => (
<ColumnItem
key={item.id}
item={item}
json={json}
isSelected={selectedPath.includes(item.id)}
isHighlighted={
highlightedPath[highlightedPath.length - 1] === item.id
}
onClick={(id) => goToNodeId(id, "columnView")}
/>
))}
</Column>
);
})}
{highlightedItemIsValue ? <BlankColumn /> : null}
+20
View File
@@ -0,0 +1,20 @@
import { useHotkeys } from "react-hotkeys-hook";
import { useSelectedInfo } from "../hooks/useSelectedInfo";
export function CopySelectedNodeShortcut() {
const selectedInfo = useSelectedInfo();
useHotkeys(
'shift+c,shift+C',
(e) => {
e.preventDefault();
const selectedJSON = selectedInfo?.name === "string"
? selectedInfo?.value
: JSON.stringify(selectedInfo?.value, null, 2);
navigator.clipboard.writeText(selectedJSON);
},
[selectedInfo]
);
return <></>;
}
+57 -43
View File
@@ -16,52 +16,66 @@ export function DocumentTitle() {
}
}, [updateDoc]);
const startEditing = useCallback(() => {
ref.current?.select();
ref.current?.focus();
}, [ref.current]);
return (
<updateDoc.Form method="post" action={`/actions/${doc.id}/update`}>
if (doc.readOnly) {
return (
<div
className="flex justify-center items-center w-full"
title={doc.title}
>
<label className="relative block group">
<PencilAltIcon className="h-5 w-5 absolute top-1/2 transform -translate-y-1/2 left-3 text-white opacity-0 transition pointer-events-none group-hover:opacity-80 group-focus:opacity-80" />
<input
ref={ref}
className={
"min-w-[15vw] border-none text-ellipsis text-slate-300 px-2 pl-10 py-1 rounded-sm bg-transparent placeholder:text-slate-400 focus:bg-black/30 focus:outline-none focus:border-none hover:bg-black hover:bg-opacity-30 hover:cursor-text transition dark:bg-transparent dark:text-slate-200 dark:placeholder:text-slate-400 dark:focus:bg-black dark:focus:bg-opacity-10 dark:hover:bg-black dark:hover:bg-opacity-10"
}
type="text"
name="title"
spellCheck="false"
placeholder="Name your JSON file"
value={editedTitle}
onChange={(e) => setEditedTitle(e.target.value)}
/>
</label>
{match(editedTitle)
.with(doc.title, () => <p className="ml-2 text-transparent">Save</p>)
.with("", () => (
<button
className="ml-2 text-lime-500 hover:text-lime-600 transition"
onClick={() => setEditedTitle(doc.title)}
>
Reset
</button>
))
.otherwise(() => (
<button
type="submit"
className="ml-2 text-lime-500 hover:text-lime-600 transition"
>
Save
</button>
))}
<span
className={
"min-w-[15vw] border-none text-ellipsis text-slate-300 px-2 pl-10 py-1 rounded-sm bg-transparent placeholder:text-slate-400 focus:bg-black/30 focus:outline-none focus:border-none hover:cursor-text transition dark:bg-transparent dark:text-slate-200 dark:placeholder:text-slate-400 dark:focus:bg-black dark:focus:bg-opacity-10"
}
>
{doc.title}
</span>
</div>
</updateDoc.Form>
);
);
} else {
return (
<updateDoc.Form method="post" action={`/actions/${doc.id}/update`}>
<div
className="flex justify-center items-center w-full"
title={doc.title}
>
<label className="relative block group">
<PencilAltIcon className="h-5 w-5 absolute top-1/2 transform -translate-y-1/2 left-3 text-white opacity-0 transition pointer-events-none group-hover:opacity-80 group-focus:opacity-80" />
<input
ref={ref}
className={
"min-w-[15vw] border-none text-ellipsis text-slate-300 px-2 pl-10 py-1 rounded-sm bg-transparent placeholder:text-slate-400 focus:bg-black/30 focus:outline-none focus:border-none hover:bg-black hover:bg-opacity-30 hover:cursor-text transition dark:bg-transparent dark:text-slate-200 dark:placeholder:text-slate-400 dark:focus:bg-black dark:focus:bg-opacity-10 dark:hover:bg-black dark:hover:bg-opacity-10"
}
type="text"
name="title"
spellCheck="false"
placeholder="Name your JSON file"
value={editedTitle}
onChange={(e) => setEditedTitle(e.target.value)}
/>
</label>
{match(editedTitle)
.with(doc.title, () => (
<p className="ml-2 text-transparent">Save</p>
))
.with("", () => (
<button
className="ml-2 text-lime-500 hover:text-lime-600 transition"
onClick={() => setEditedTitle(doc.title)}
>
Reset
</button>
))
.otherwise(() => (
<button
type="submit"
className="ml-2 text-lime-500 hover:text-lime-600 transition"
>
Save
</button>
))}
</div>
</updateDoc.Form>
);
}
}
+20
View File
@@ -0,0 +1,20 @@
import { Link } from "remix";
export function ExampleDoc({
id,
title,
path,
}: {
id: string;
title: string;
path?: string;
}) {
return (
<Link
to={`/j/${id}${path ? `?path=${path}` : ""}`}
className="bg-slate-900 px-4 py-2 rounded-md whitespace-nowrap text-lime-300 transition hover:text-lime-500"
>
{title}
</Link>
);
}
+7
View File
@@ -1,4 +1,5 @@
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";
@@ -26,6 +27,12 @@ export function Footer() {
Reset path
</Body>
</li>
<li className="flex items-center">
<CopyShortcutIcon className="transition text-slate-300 dark:text-slate-500" />
<Body className="pl-2 pr-4 text-slate-800 transition dark:text-white">
Copy selected node
</Body>
</li>
</ol>
<ThemeModeToggler />
</footer>
+6
View File
@@ -2,6 +2,7 @@ import { DiscordIcon } from "../Icons/DiscordIcon";
import { EmailIcon } from "../Icons/EmailIcon";
import { GithubIcon } from "../Icons/GithubIcon";
import { Logo } from "../Icons/Logo";
import { TwitterIcon } from "../Icons/TwitterIcon";
export type HomeFooterProps = {
maxWidth?: string;
@@ -36,6 +37,11 @@ export function HomeFooter({ maxWidth = "1150px" }: HomeFooterProps) {
<DiscordIcon />
</a>
</li>
<li className="ml-2 hover:cursor-pointer">
<a href="https://twitter.com/json_hero" target="_blank">
<TwitterIcon />
</a>
</li>
</ol>
</div>
</footer>
+7 -1
View File
@@ -1,5 +1,6 @@
import { DiscordIconTransparent } from "../Icons/DiscordIconTransparent";
import { EmailIconTransparent } from "../Icons/EmailIconTransparent";
import { TwitterIcon } from "../Icons/TwitterIcon";
import { Logo } from "../Icons/Logo";
import { NewDocument } from "../NewDocument";
import { GithubStar } from "../UI/GithubStar";
@@ -13,7 +14,7 @@ import {
export function HomeHeader() {
return (
<header className="fixed z-20 flex items-center justify-between w-screen h-[82px] px-4 bg-indigo-700">
<div className="flex w-44 mr-3">
<div className="flex w-36 sm:w-44 mr-3">
<Logo />
</div>
<ol className="flex items-center gap-2">
@@ -45,6 +46,11 @@ export function HomeHeader() {
<DiscordIconTransparent />
</a>
</li>
<li className="hover:cursor-pointer opacity-90 hover:opacity-100 transition">
<a href="https://twitter.com/json_hero" target="_blank">
<TwitterIcon />
</a>
</li>
</ol>
</header>
);
+7 -1
View File
@@ -142,7 +142,13 @@ function SampleJSONPreview({
}) {
return (
<JsonDocProvider
doc={{ id: "sample", title: "Sample", type: "raw", contents: "" }}
doc={{
id: "sample",
title: "Sample",
type: "raw",
readOnly: false,
contents: "",
}}
path={initialSelection}
>
<JsonProvider initialJson={json}>
+23
View File
@@ -0,0 +1,23 @@
export function CopyShortcutIcon(props: React.SVGProps<SVGSVGElement>) {
return (
<svg
className={props.className}
width="30"
height="14"
viewBox="0 0 30 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect width="14" height="14" rx="1.53846" fill="currentColor" />
<rect x="16" width="14" height="14" rx="1.53846" fill="currentColor" />
<path
d="M5.64,10.22H8.25V7a.39.39,0,0,1,.38-.39H10l-3-3L4,6.65H5.26A.39.39,0,0,1,5.64,7v3.18Zm3,.78H5.26a.38.38,0,0,1-.39-.39V7.43H3.11a.39.39,0,0,1-.28-.66L6.72,2.86a.39.39,0,0,1,.55,0l3.88,3.91a.38.38,0,0,1-.27.66H9v3.18a.38.38,0,0,1-.39.39Z"
stroke="#0f172a" strokeWidth="0.35px" fill="#0f172a"
/>
<path
d="M23.81,9.52a1.66,1.66,0,0,0,.53-.27,1.57,1.57,0,0,0,.35-.42,1.07,1.07,0,0,0,.13-.53h1.6a2.26,2.26,0,0,1-.25,1,2.87,2.87,0,0,1-.7.85,3.35,3.35,0,0,1-1,.58,3.56,3.56,0,0,1-1.22.21,3.73,3.73,0,0,1-1.55-.31,3.2,3.2,0,0,1-1.11-.84,3.61,3.61,0,0,1-.67-1.22,4.91,4.91,0,0,1-.23-1.5V6.88a4.91,4.91,0,0,1,.23-1.5,3.54,3.54,0,0,1,.67-1.22,3.33,3.33,0,0,1,1.11-.84,3.94,3.94,0,0,1,2.83-.09,3,3,0,0,1,1,.59,2.66,2.66,0,0,1,.67.92,2.94,2.94,0,0,1,.23,1.17h-1.6a1.48,1.48,0,0,0-.45-1.07,1.65,1.65,0,0,0-.52-.33,1.75,1.75,0,0,0-.65-.12,1.59,1.59,0,0,0-1.44.78,2.27,2.27,0,0,0-.31.8,4.53,4.53,0,0,0-.09.91v.24a4.63,4.63,0,0,0,.09.92,2.46,2.46,0,0,0,.3.8,1.67,1.67,0,0,0,.56.56,1.63,1.63,0,0,0,.89.22A2.05,2.05,0,0,0,23.81,9.52Z"
fill="#0f172a"
/>
</svg>
);
}
+1 -9
View File
@@ -4,24 +4,16 @@ 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";
export function InfoPanel() {
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">
@@ -34,7 +26,7 @@ export function InfoPanel() {
<ContainerInfo />
{isSelectedLeafNode && <RelatedValues relatedPaths={relatedPaths} />}
<RelatedValues relatedPaths={relatedPaths} />
</div>
</>
);
+4 -1
View File
@@ -4,6 +4,7 @@ import {
} from "../hooks/useJsonColumnView";
import { useHotkeys } from "react-hotkeys-hook";
import { Columns } from "./Columns";
import { CopySelectedNodeShortcut } from "./CopySelectedNode";
export function JsonColumnView() {
const { getColumnViewProps, columns } = useJsonColumnViewState();
@@ -67,5 +68,7 @@ function KeyboardShortcuts() {
[api]
);
return <></>;
return <>
<CopySelectedNodeShortcut />
</>;
}
+1 -1
View File
@@ -81,7 +81,7 @@ export function JsonEditor() {
<CodeEditor
language="json"
content={jsonMapped.json}
readOnly={false}
readOnly={true}
onUpdate={onUpdate}
selection={selection}
/>
+26 -22
View File
@@ -6,6 +6,7 @@ import {
} from "~/hooks/useJsonColumnView";
import { JsonTreeViewNode, useJsonTreeViewContext } from "~/hooks/useJsonTree";
import { VirtualNode } from "~/hooks/useVirtualTree";
import { CopySelectedNodeShortcut } from "./CopySelectedNode";
import { Body } from "./Primitives/Body";
import { Mono } from "./Primitives/Mono";
@@ -78,31 +79,34 @@ export function JsonTreeView() {
}, [treeRef.current]);
return (
<div
className="text-white w-full"
ref={parentRef}
style={{
height: `calc(100vh - 106px)`,
overflowY: "auto",
overflowX: "hidden",
}}
>
<>
<CopySelectedNodeShortcut />
<div
className="relative w-full outline-none"
style={{ height: `${tree.totalSize}px` }}
{...tree.getTreeProps()}
ref={treeRef}
className="text-white w-full"
ref={parentRef}
style={{
height: `calc(100vh - 106px)`,
overflowY: "auto",
overflowX: "hidden",
}}
>
{tree.nodes.map((virtualNode) => (
<TreeViewNode
virtualNode={virtualNode}
key={virtualNode.node.id}
onToggle={(node, e) => tree.toggleNode(node.id, e)}
selectedNodeId={selectedNodeId}
/>
))}
<div
className="relative w-full outline-none"
style={{ height: `${tree.totalSize}px` }}
{...tree.getTreeProps()}
ref={treeRef}
>
{tree.nodes.map((virtualNode) => (
<TreeViewNode
virtualNode={virtualNode}
key={virtualNode.node.id}
onToggle={(node, e) => tree.toggleNode(node.id, e)}
selectedNodeId={selectedNodeId}
/>
))}
</div>
</div>
</div>
</>
);
}
@@ -0,0 +1,42 @@
import { useRef } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { Body } from "~/components/Primitives/Body";
import { PreviewBox } from "../PreviewBox";
export function PreviewAudioUri({
src,
contentType,
}: {
src: string;
contentType: string;
}) {
const mediaRef = useRef<HTMLMediaElement>(null);
useHotkeys(
"space",
(e) => {
e.preventDefault();
if (mediaRef.current) {
if (mediaRef.current.paused) {
mediaRef.current.play();
} else {
mediaRef.current.pause();
}
}
},
[mediaRef]
);
return (
<div>
<PreviewBox>
<Body>
<audio controls src={src} ref={mediaRef}>
Sorry, your browser doesn't support embedded audio.
</audio>
</Body>
</PreviewBox>
</div>
);
}
@@ -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>
+32 -1
View File
@@ -6,9 +6,12 @@ import {
import Color from "color";
import { CodeViewer } from "~/components/CodeViewer";
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";
export function PreviewString({ info }: { info: JSONStringType }) {
if (info.format == null) {
@@ -23,9 +26,37 @@ export function PreviewString({ info }: { info: JSONStringType }) {
info.format.contentType === "image/gif" ||
info.format.contentType === "image/svg+xml" ||
info.format.contentType === "image/webp"
) {
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" ||
info.format.contentType === "video/ogg"
) {
return (
<PreviewImageUri
<PreviewVideoUri
src={info.value}
contentType={info.format.contentType}
/>
);
} else if (
info.format.contentType === "audio/mpeg" ||
info.format.contentType === "audio/ogg" ||
info.format.contentType === "audio/wav"
) {
return (
<PreviewAudioUri
src={info.value}
contentType={info.format.contentType}
/>
@@ -0,0 +1,43 @@
import { useRef } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { Body } from "~/components/Primitives/Body";
import { PreviewBox } from "../PreviewBox";
export function PreviewVideoUri({
src,
contentType,
}: {
src: string;
contentType: string;
}) {
const videoRef = useRef<HTMLVideoElement>(null);
useHotkeys(
"space",
(e) => {
e.preventDefault();
if (videoRef.current) {
if (videoRef.current.paused) {
videoRef.current.play();
} else {
videoRef.current.pause();
}
}
},
[videoRef]
);
return (
<div>
<PreviewBox>
<Body>
<video key={src} controls ref={videoRef}>
<source src={src} type={contentType} />
Sorry, your browser doesn't support embedded videos.
</video>
</Body>
</PreviewBox>
</div>
);
}
+14 -17
View File
@@ -1,31 +1,28 @@
import { ExampleDoc } from "./ExampleDoc";
import { ExampleUrl } from "./ExampleUrl";
export function SampleUrls() {
return (
<div className="flex justify-start flex-wrap gap-2">
<ExampleUrl
url="https://gist.githubusercontent.com/ericallam/332aca65c34dbc0fdb1b3cffbdf3f7a4/raw/4c6e264c3afd3432b608bad628290a7d71035253/unsplash.json"
title="Unsplash API Example"
displayTitle="Unsplash API"
<ExampleDoc
id="xW6aDgcbKgwC"
title="Unsplash API"
path="4.urls.regular"
/>
<ExampleUrl
url="https://gist.githubusercontent.com/ericallam/77e37e93e370b32387ce8d598dd06fc8/raw/9306a2c039fc27ab42bdadb80cbd6dbca49d27ec/tweet.json"
title="Tweet API Example"
displayTitle="Tweet JSON"
<ExampleDoc
id="d9udW60cLOok"
title="Tweet JSON"
path="data.0.entities.urls.0.expanded_url"
/>
<ExampleUrl
url="https://gist.githubusercontent.com/ericallam/f11f4981adf72b0427427c349afb3a09/raw/37eee4234b628f3278c9d4f644fee4a1c4987593/Airtable.json"
title="Airtable Product Catalog"
displayTitle="Airtable API"
<ExampleDoc
id="JZw4Wx9Mgj6r"
title="Airtable API"
path="records.3.createdTime"
/>
<ExampleUrl
url="https://gist.githubusercontent.com/ericallam/51b77c0051c21a34ea33d601bb0b1bef/raw/0b099f7d3bb5fe47f1fd55007d6a5fe9c5fd046b/GitHub.json"
title="List of Github Repos"
displayTitle="Github API"
/>
<ExampleDoc id="PjHo1o5MVeH4" title="Github API" />
</div>
);
}
+80
View File
@@ -0,0 +1,80 @@
import * as ToastPrimitive from "@radix-ui/react-toast";
import cx from "~/utilities/classnames";
import React from "react";
import { Body } from "../Primitives/Body";
import { Title } from "../Primitives/Title";
type Props = {};
const Toast = (props: Props) => {
const [open, setOpen] = React.useState(false);
return (
<ToastPrimitive.Provider>
<button
onClick={() => {
if (open) {
setOpen(false);
setTimeout(() => {
setOpen(true);
}, 500);
} else {
setOpen(true);
}
}}
>
Click
</button>
<ToastPrimitive.Root
open={open}
onOpenChange={setOpen}
className={cx(
"z-50 fixed bottom-4 inset-x-4 w-auto md:top-4 md:right-2 md:left-auto md:bottom-auto md:w-full md:max-w-sm shadow-lg rounded-md",
"bg-slate-100 dark:bg-slate-900 border-[1px] border-slate-200 dark:border-black",
"radix-state-open:animate-toast-slide-in-bottom md:radix-state-open:animate-toast-slide-in-right",
"radix-state-closed:animate-toast-hide",
"radix-swipe-end:animate-toast-swipe-out",
"translate-x-radix-toast-swipe-move-x",
"radix-swipe-cancel:translate-x-0 radix-swipe-cancel:duration-200 radix-swipe-cancel:ease-[ease]",
"focus:outline-none focus-visible:ring focus-visible:ring-indigo-500 focus-visible:ring-opacity-75"
)}
>
<div className="flex">
<div className="w-0 flex-1 flex items-center pl-5 py-4">
<div className="w-full radix">
<Title className="dark:text-slate-200">Invalid JSON</Title>
<Body className="mt-0.5 dark:text-slate-400">
Check your JSON is valid and try again.
</Body>
</div>
</div>
<div className="flex">
<div className="flex flex-col pl-3 pr-2 py-2 space-y-1">
<div className="h-0 flex-1 flex items-center">
<ToastPrimitive.Action
altText="close"
className="w-full max-h-10 border border-transparent rounded-sm px-3 py-2 flex items-center justify-center text-md font-medium text-white bg-indigo-600 hover:bg-indigo-600/90 focus:z-10 focus:outline-none focus-visible:ring focus-visible:ring-indigo-500 focus-visible:ring-opacity-75"
onClick={(e) => {
e.preventDefault();
window.open("https://github.com");
}}
>
Primary
</ToastPrimitive.Action>
</div>
<div className="h-0 flex-1 flex">
<ToastPrimitive.Close className="w-full max-h-10 border border-transparent rounded-sm px-3 py-2 flex items-center justify-center text-md font-medium text-slate-700 dark:text-slate-100 bg-slate-300 hover:bg-slate-300/80 dark:bg-slate-700 hover:dark:bg-slate-700/80 dark:hover:bg-slate-900 focus:z-10 focus:outline-none focus-visible:ring focus-visible:ring-indigo-500 focus-visible:ring-opacity-75">
Secondary
</ToastPrimitive.Close>
</div>
</div>
</div>
</div>
</ToastPrimitive.Root>
<ToastPrimitive.Viewport />
</ToastPrimitive.Provider>
);
};
export default Toast;
+30 -4
View File
@@ -1,8 +1,10 @@
import { customRandom } from "nanoid";
import safeFetch from "./utilities/safeFetch";
type BaseJsonDocument = {
id: string;
title: string;
readOnly: boolean;
};
export type RawJsonDocument = BaseJsonDocument & {
@@ -17,6 +19,8 @@ export type UrlJsonDocument = BaseJsonDocument & {
export type CreateJsonOptions = {
ttl?: number;
readOnly?: boolean;
injest?: boolean;
metadata?: any;
};
@@ -37,17 +41,33 @@ export async function createFromUrlOrRawJson(
export async function createFromUrl(
url: URL,
title?: string
title?: string,
options?: CreateJsonOptions
): Promise<JSONDocument> {
if (options?.injest) {
const response = await safeFetch(url.href);
if (!response.ok) {
throw new Error(`Failed to injest ${url.href}`);
}
return createFromRawJson(title || url.href, await response.text(), options);
}
const docId = createId();
const doc = {
const doc: JSONDocument = {
id: docId,
type: <const>"url",
url: url.href,
title: title ?? url.hostname,
readOnly: options?.readOnly ?? false,
};
await DOCUMENTS.put(docId, JSON.stringify(doc));
await DOCUMENTS.put(docId, JSON.stringify(doc), {
expirationTtl: options?.ttl ?? undefined,
metadata: options?.metadata ?? undefined,
});
return doc;
}
@@ -58,7 +78,13 @@ export async function createFromRawJson(
options?: CreateJsonOptions
): Promise<JSONDocument> {
const docId = createId();
const doc = { id: docId, type: <const>"raw", contents, title: filename };
const doc: JSONDocument = {
id: docId,
type: <const>"raw",
contents,
title: filename,
readOnly: options?.readOnly ?? false,
};
await DOCUMENTS.put(docId, JSON.stringify(doc), {
expirationTtl: options?.ttl ?? undefined,
+9 -1
View File
@@ -28,6 +28,7 @@ import { Body } from "~/components/Primitives/Body";
import { PageNotFoundTitle } from "~/components/Primitives/PageNotFoundTitle";
import { SmallSubtitle } from "~/components/Primitives/SmallSubtitle";
import { Logo } from "~/components/Icons/Logo";
import ToastPopover from "~/components/UI/ToastPopover";
export const loader: LoaderFunction = async ({ params, request }) => {
invariant(params.id, "expected params.id");
@@ -48,6 +49,10 @@ export const loader: LoaderFunction = async ({ params, request }) => {
const jsonResponse = await safeFetch(doc.url);
if (!jsonResponse.ok) {
console.log(
`Failed to fetch ${doc.url}: ${jsonResponse.status} (${jsonResponse.statusText})`
);
throw new Response(jsonResponse.statusText, {
status: jsonResponse.status,
});
@@ -55,6 +60,8 @@ export const loader: LoaderFunction = async ({ params, request }) => {
const json = await jsonResponse.json();
console.log(`Fetched ${doc.url} with json, returning...`);
return {
doc,
json,
@@ -119,13 +126,14 @@ export default function JsonDocumentRoute() {
path={loaderData.path}
key={loaderData.doc.id}
>
<ToastPopover />
<JsonProvider initialJson={loaderData.json}>
<JsonSchemaProvider>
<JsonColumnViewProvider>
<JsonSearchProvider>
<JsonTreeViewProvider overscan={25}>
<div>
<div className="block sm:hidden fixed bg-black/80 h-screen w-screen z-50 text-white">
<div className="block md:hidden fixed bg-black/80 h-screen w-screen z-50 text-white">
<div className="flex flex-col items-center justify-center h-full text-center">
<LargeTitle>JSON Hero only works on desktop</LargeTitle>
<LargeTitle>👇</LargeTitle>
+34 -4
View File
@@ -1,23 +1,49 @@
import { LoaderFunction, redirect } from "remix";
import { json, LoaderFunction, redirect } from "remix";
import invariant from "tiny-invariant";
import { sendEvent } from "~/graphJSON.server";
import { createFromRawJson, createFromUrl } from "~/jsonDoc.server";
import {
createFromRawJson,
createFromUrl,
CreateJsonOptions,
} from "~/jsonDoc.server";
export let loader: LoaderFunction = async ({ request, context }) => {
const url = new URL(request.url);
const jsonUrl = url.searchParams.get("url");
const base64EncodedJson = url.searchParams.get("j");
const ttl = url.searchParams.get("ttl");
const readOnly = url.searchParams.get("readonly");
const title = url.searchParams.get("title");
const injest = url.searchParams.get("injest");
if (!jsonUrl && !base64EncodedJson) {
return redirect("/");
}
const options: CreateJsonOptions = {};
if (typeof ttl === "string") {
invariant(ttl.match(/^\d+$/), "ttl must be a number");
options.ttl = parseInt(ttl, 10);
invariant(options.ttl >= 60, "ttl must be at least 60 seconds");
}
if (typeof readOnly === "string") {
options.readOnly = readOnly === "true";
}
if (typeof injest === "string") {
options.injest = injest === "true";
}
if (jsonUrl) {
const jsonURL = new URL(jsonUrl);
invariant(jsonURL, "url must be a valid URL");
const doc = await createFromUrl(jsonURL, jsonURL.href);
const doc = await createFromUrl(jsonURL, title ?? jsonURL.href, options);
context.waitUntil(
sendEvent({
@@ -33,7 +59,11 @@ export let loader: LoaderFunction = async ({ request, context }) => {
}
if (base64EncodedJson) {
const doc = await createFromRawJson("Untitled", atob(base64EncodedJson));
const doc = await createFromRawJson(
title ?? "Untitled",
atob(base64EncodedJson),
options
);
context.waitUntil(
sendEvent({
+8 -22
View File
@@ -1,17 +1,6 @@
// Should truncate the number to not show the exact number of stars
// If over 1000, show 1k
// If between 1100 and 1199, show 1.1k
// If between 1200 and 1299, show 1.2k
// If between 1300 and 1399, show 1.3k
// If over 10000, show 10k
// if between 10100 and 10199, show 10.1k
// if between 10200 and 10299, show 10.2k
// if between 10300 and 10399, show 10.3k
// if between 11000 and 11099, show 11k
// if between 11100 and 11199, show 11.1k
// if over 100000, show 100k
// if between 100100 and 100199, show 100.1k
// if between 100200 and 100299, show 100.2k
// Round up to the nearest hundred, so for example, 1150 becomes 1.2k, 1101 becomes 1.1k, etc.
export function formatStarCount(count: number | undefined): string {
if (count === undefined) {
return "⭐️";
@@ -20,14 +9,11 @@ export function formatStarCount(count: number | undefined): string {
if (count < 1000) {
return count.toString();
}
if (count < 10000) {
return `${Math.floor(count / 100) / 10}k`;
}
if (count < 100000) {
return `${Math.floor(count / 100) / 10}k`;
}
if (count < 1000000) {
return `${Math.floor(count / 100) / 10}k`;
}
return `${Math.floor(count / 100000)}k`;
return `${roundWithPrecision(count / 1000, 1)}k`;
}
function roundWithPrecision(value: number, precision: number): number {
const multiplier = Math.pow(10, precision);
return Math.round(value * multiplier) / multiplier;
}
+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;
+402
View File
@@ -0,0 +1,402 @@
[
{
"movie": "Cars 3",
"year": 2017,
"release_date": "2017-05-23",
"director": "Brian Fee",
"character": "Lighting McQueen",
"movie_duration": "01:42:25",
"timestamp": "00:25:10",
"full_line": "Oh, hey, Mr. Sterling. Wow.",
"current_wow_in_movie": 3,
"total_wows_in_movie": 10,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/43fOBsgY8iOJL0dijvFnfl/ea361efc5131a859c173ab5dd3fdfe1e/Cars_3_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/MwAHRe21gYt7qgtQqQSgi/20188401d4ae548db5c4f861fad96f49/Cars_3_Wow_3_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/7dL6LdSOmZ2mbXgdi4KeZl/6fe6efef423d28e5704637658a3650ec/Cars_3_Wow_3_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/7uciNXhLeVXBByZu8ipAr4/5bcae43dde19fa0bb249e9318953ba09/Cars_3_Wow_3_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/KL91bYDqfWVeK6NdaXh1O/f1baca7b2988a2e5853256be5f9e2c89/Cars_3_Wow_3_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/6PlYbs7cO3iXEEM1szcfHZ/bf10fba861c8e0d2c20ac4714974bde1/Cars_3_Wow_3.mp3"
},
{
"movie": "The Internship",
"year": 2013,
"release_date": "2013-05-29",
"director": "Shawn Levy",
"character": "Nick Campbell",
"movie_duration": "02:05:02",
"timestamp": "00:38:59",
"full_line": "Wow! Seven projects.",
"current_wow_in_movie": 1,
"total_wows_in_movie": 5,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6XhmTpc1PoiTf0q1nDYMyv/594947f72b4dba7f3c24938a680dd603/The_Internship_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/11VKtDgrvqvU4atLRF9QV9/f1f1ae91486a001e41fb3f66821f1e62/The_Internship_Wow_1_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/6uDteZpujqfebwhVAXoFkm/768bbb0a63dcef265b0040b54e417483/The_Internship_Wow_1_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/4JTqjEo1kTWtALpSdE9pVs/f9242e24e89c9bd32aa3f5212eca08e9/The_Internship_Wow_1_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/5VGJ7XEkBhxEbLMuDR4AIC/e5b80d57316dbb910cd72685f72b8f2b/The_Internship_Wow_1_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/2vwdiSubw2iEcsl1yCUk0A/3cb1ba763c12fd7711823619b4c3d904/The_Internship_Wow_1.mp3"
},
{
"movie": "Cars 3",
"year": 2017,
"release_date": "2017-05-23",
"director": "Brian Fee",
"character": "Lighting McQueen",
"movie_duration": "01:42:25",
"timestamp": "01:03:08",
"full_line": "Wow. You don't mince words around here, do you?",
"current_wow_in_movie": 10,
"total_wows_in_movie": 10,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/43fOBsgY8iOJL0dijvFnfl/ea361efc5131a859c173ab5dd3fdfe1e/Cars_3_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/3KJZ435sr6Y5k00AnZdOJ2/2aadc7fbc687b38c3f1536a9efc16cdb/Cars_3_Wow_10_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/5vQtn6ny9J79PNG16jsJMR/1b4804366cfb9206d70472ab9b7f37e6/Cars_3_Wow_10_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/6kIDoftFyBJOgvCBe5Jr5k/51be6dcd0a40aff052a4215258f6f2cb/Cars_3_Wow_10_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/923BnYGWVuiPpWeM7e6wv/db39600a6bd7c6a807e95d397d129dd4/Cars_3_Wow_10_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/3iZaUMMLnxCH1fIqcXpYZ0/78e6ee967cae46e64a6f65c6f451115a/Cars_3_Wow_10.mp3"
},
{
"movie": "Night at the Museum: Secret of the Tomb",
"year": 2014,
"release_date": "2014-12-11",
"director": "Shawn Levy",
"character": "Jedediah Smith",
"movie_duration": "01:37:48",
"timestamp": "00:39:36",
"full_line": "Wow. We're a long way from home, boy.",
"current_wow_in_movie": 1,
"total_wows_in_movie": 1,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/4cwNnRAOKM1HuAtlH6dscl/52762736d4815c2390619a4009d66d93/Night_at_the_Museum_Secret_of_the_Tomb_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/uHF5B0MFoK8H0S40Sqld9/fa9aca4d8c52ebff4ab4f390196ab0f1/Night_at_the_Museum_Secret_of_the_Tomb_Wow_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/47qSLctyurmw22A3z7X1YG/8651f02d7e58ebb1eb312a26f732515b/Night_at_the_Museum_Secret_of_the_Tomb_Wow_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/3ZLiolsGZkiTp3p8aLJb3d/e330311fcaed4716f7a603d058ee8767/Night_at_the_Museum_Secret_of_the_Tomb_Wow_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/1ZwmDYe0zdKzsy1MJrANSE/e5e0f5ea1c745baf61b205b6e6574605/Night_at_the_Museum_Secret_of_the_Tomb_Wow_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/5o3CSC67KEoIojYH0UMghP/fbf9dea48ac1914eb7f7bffca802b012/Night_at_the_Museum_Secret_of_the_Tomb_Wow.mp3"
},
{
"movie": "The Internship",
"year": 2013,
"release_date": "2013-05-29",
"director": "Shawn Levy",
"character": "Nick Campbell",
"movie_duration": "02:05:02",
"timestamp": "01:26:54",
"full_line": "You're so cute. It's beautiful. Wow.",
"current_wow_in_movie": 4,
"total_wows_in_movie": 5,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6XhmTpc1PoiTf0q1nDYMyv/594947f72b4dba7f3c24938a680dd603/The_Internship_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/61gtrYzY8qsD3Onc4hUNdx/e1685933255e13fce8578594dbfc30aa/The_Internship_Wow_4_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/3CQQDswj7JP1UU95KdHZ2x/af3e2709d1b8c730a177a56e0395bce3/The_Internship_Wow_4_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/67gEv3fXOzKu5IsscIYAxw/bf8e18b6543eec4ac1952d6c6845cb8f/The_Internship_Wow_4_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/1ZrN3pCfLhimJ2fxxf86n3/43116038f56d789a1514778081c7dcc2/The_Internship_Wow_4_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/5Jphk5c8qFsc7ZiWNeJOKQ/80f43d3758ee8730987c6a859ffec667/The_Internship_Wow_4.mp3"
},
{
"movie": "Cars 3",
"year": 2017,
"release_date": "2017-05-23",
"director": "Brian Fee",
"character": "Lighting McQueen",
"movie_duration": "01:42:25",
"timestamp": "00:22:42",
"full_line": "Wow!",
"current_wow_in_movie": 2,
"total_wows_in_movie": 10,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/43fOBsgY8iOJL0dijvFnfl/ea361efc5131a859c173ab5dd3fdfe1e/Cars_3_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/1xpGU65BqXMplnWjcs0HG7/19ad3a66f22c976b7a345ba7a2d931ce/Cars_3_Wow_2_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/NXF2Haueh2DGbaHOpLDuV/21d43d80d211f6f93062b4f35c6d68ba/Cars_3_Wow_2_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/6mN4TgA3TUcgqUEec3qCOV/c30c18bc851f43db95b3cab17aea0fb0/Cars_3_Wow_2_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/316quJhdUfAkcmKkzPjww0/1780af73d03a7a631c71429d59a064e9/Cars_3_Wow_2_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/7rkrQVW7vsUj6amBflfTQ9/fe38afabd1eeaed70d14a8bbcf68d417/Cars_3_Wow_2.mp3"
},
{
"movie": "Hall Pass",
"year": 2011,
"release_date": "2011-02-25",
"director": "Peter Farrelly and Bobby Farrelly",
"character": "Rick Mills",
"movie_duration": "01:51:35",
"timestamp": "01:26:28",
"full_line": "Wow.",
"current_wow_in_movie": 6,
"total_wows_in_movie": 6,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6jFEUPmYiKifaTuC2cugm8/22087834d091445fc9393cdd9163a901/Hall_Pass_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/V9JGQ3qgfufm4vUkzyJYI/6182dce642b9f31ab698d7ab448688bd/Hall_Pass_Wow_6_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/3RkKyI4NFfakkYzUEO83hG/21d29c6b7695d1b072084a92e05b6283/Hall_Pass_Wow_6_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/54Zd2b5BQrQi4hvZ8IAg8j/9a719307cdf6525257e0dba0afa9ceee/Hall_Pass_Wow_6_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/7Jo3JA6zl3vzAiIkriLLOR/5f488e12cdc1c7792484f098732b790d/Hall_Pass_Wow_6_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/7mZxDvl1IsR95NAg8mKj0t/43a0b44fd325c1de3f86cf6cec3a80d5/Hall_Pass_Wow_6.mp3"
},
{
"movie": "Cars",
"year": 2006,
"release_date": "2006-06-09",
"director": "John Lasseter",
"character": "Lightning McQueen",
"movie_duration": "01:56:36",
"timestamp": "01:23:13",
"full_line": "Wow, you were right!",
"current_wow_in_movie": 4,
"total_wows_in_movie": 5,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6dsHUil72TJLYqbwYMEjH4/387a2d9994a2f1fb069d970a0f30ba32/Cars_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/5WH68GXLSVdosuz0ouwFDF/0b55b456669a8bf8a13e6aecd46cae89/Cars_Wow_4_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/7KSwlI2izHJDNtiGAH32SU/7d7698ac27be72753ddc1e2291399b46/Cars_Wow_4_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/6OExsgI6VJHXcjNZtlqBkx/3152bd6700486416ec0b818829de9374/Cars_Wow_4_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/2ibZvAYOWwmoqQtANL3d8o/9c09f29a7f42ecd996ac991b52b2cc65/Cars_Wow_4_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/iJ5LIuyc3pmvEAaiSVSLS/85e36dc0324b28549ea56a6882a03062/Cars_Wow_4.mp3"
},
{
"movie": "The Big Bounce",
"year": 2004,
"release_date": "2004-01-30",
"director": "George Armitage",
"character": "Jack Ryan",
"movie_duration": "01:28:10",
"timestamp": "00:58:00",
"full_line": "What is it about the produce section? Wow.",
"current_wow_in_movie": 2,
"total_wows_in_movie": 2,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/4hPpMWXhuXQ8HzLusmcaS5/4c46fa4fa8bce13b06d8b4444f6150ef/The_Big_Bounce_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/6TPALdqhVTMztHMSw2qOOj/81d512b2ee8b7c05e7e851eae7790d0e/The_Big_Bounce_Wow_2_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/dEuiSxnBLWP26YHaWiHbz/599ac6fb7a6aead87e8e6efdab759f74/The_Big_Bounce_Wow_2_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/7tA15W0lgJr7CpJNCf1m4Z/86a953df81d88f5fa79e35aa1e4e4dc1/The_Big_Bounce_Wow_2_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/1iKZTtL0qQRDek4y4SduD5/bbd83798b30435b43a2df4c360130d72/The_Big_Bounce_Wow_2_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/6pjOYj0xK38VAkPAl1QK7R/a5f083c60ce9e9c4fa93a8be70817d22/The_Big_Bounce_Wow_2.mp3"
},
{
"movie": "The Big Year",
"year": 2011,
"release_date": "2011-10-14",
"director": "David Frankel",
"character": "Kenny Bostick",
"movie_duration": "01:43:09",
"timestamp": "01:08:23",
"full_line": "Wow, and here I thought I was the bomb at 728.",
"current_wow_in_movie": 3,
"total_wows_in_movie": 3,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/pCjGOhbTCQVjLRN9zTwIi/ce7cdf4b40f3549326d881697aa468a1/The_Big_Year_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/uOdKu6VANHZjtwZXeBU8M/bf1f0f44c7bc01faa648a1b97b1205d3/The_Big_Year_Wow_3_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/y9wR96fHZaNnZr367mjyI/1262c2af0400cb1dc8528c3c8e6a83a4/The_Big_Year_Wow_3_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/55z94kbUxNFIL0rYb1i2mH/ca0505ca5e2017b663f18cca8af571b2/The_Big_Year_Wow_3_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6moRL0SzmkTGzgEuZeVByI/c63fa33d0992c0594ecbaed4fcd7e891/The_Big_Year_Wow_3_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/1dXEYZQP1Fl6CX1roy7ZAH/f31b90a6f961dcc16c16b294f4faf664/The_Big_Year_Wow_3.mp3"
},
{
"movie": "Hall Pass",
"year": 2011,
"release_date": "2011-02-25",
"director": "Peter Farrelly and Bobby Farrelly",
"character": "Rick Mills",
"movie_duration": "01:51:35",
"timestamp": "00:46:55",
"full_line": "Wow. This is awkward. I feel like I'm at my first junior high mixer. You know? When you don't know what to say.",
"current_wow_in_movie": 3,
"total_wows_in_movie": 6,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6jFEUPmYiKifaTuC2cugm8/22087834d091445fc9393cdd9163a901/Hall_Pass_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/4QcL02MHJ8ApVkbfN8cP6E/264c28c1e9195d87f0206e143c5ca54a/Hall_Pass_Wow_3_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/15h0sMoIhdeaPDB8qSsUN9/36245f66352b595dc40bc4d9903fa5b3/Hall_Pass_Wow_3_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/74fQiVcwuT7ePQemGC7ih4/b102922c97c9ff38f47268d648628a22/Hall_Pass_Wow_3_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/7mSGl1rSVtGdfSacwnKVsu/e7ac36e5684f6b64978987d2f68c43db/Hall_Pass_Wow_3_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/2NBIVPDF4o7cy0epTvPOwR/406cd5c17e9b01511f1e350bb96df352/Hall_Pass_Wow_3.mp3"
},
{
"movie": "No Escape",
"year": 2015,
"release_date": "2015-08-26",
"director": "John Erick Dowdle",
"character": "Jack Dwyer",
"movie_duration": "01:43:06",
"timestamp": "00:08:11",
"full_line": "Wow.",
"current_wow_in_movie": 1,
"total_wows_in_movie": 2,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/R3PGhNHo0k5uhnPM7bqIp/5e2b3723c69f7c70313be19417c6fdba/No_Escape_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/3WxIt1hZQtpqnveyAb4xw3/54773cfd70ab4380c47048324f216fc4/No_Escape_Wow_1_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/2JcYMonzmocD3qABm1dpNg/019b752a33b2517033d75ea5bfd20b59/No_Escape_Wow_1_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/5QMtRpqqyfg9irqjPPx5JO/5a24212c22dc20944b5831e5b81efe4d/No_Escape_Wow_1_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6aou6AH16gfvXSccxgcZFf/347d5ff951c851d5fe9928323e6067eb/No_Escape_Wow_1_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/24lDtvWBG8mDqaqBM8Qsr0/4c08f87367dd3399efb6a5554f6f4858/No_Escape_Wow_1.mp3"
},
{
"movie": "Midnight in Paris",
"year": 2011,
"release_date": "2011-05-20",
"director": "Woody Allen",
"character": "Gil Pender",
"movie_duration": "01:33:57",
"timestamp": "00:58:22",
"full_line": "Wow.",
"current_wow_in_movie": 5,
"total_wows_in_movie": 10,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/2ZcfSCe2dlfoVzYMr4b9nK/d566e5ad044dee56645f3bffc7200d64/Midnight_in_Paris_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/1DSaYjQ8SnL1Imeuxe0eXE/100d3106c8a0bf5e80372e2187daf325/Midnight_in_Paris_Wow_5_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/eFI1n7voe4CsxkWEWv2q0/36781ed8f50e508e8e1f79c8e65e601a/Midnight_in_Paris_Wow_5_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/6oSaIzfy7k3DJMvvy3j1kN/d77192d7decb3ba9d06a5210a58df1fa/Midnight_in_Paris_Wow_5_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/4LQ4lkhx41XDC6UcMlmjbA/dfd5e3604c85c9fb9d38ea2dfdd02a2f/Midnight_in_Paris_Wow_5_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/2A5G34x8JCQBuYwU4D2l9S/27cc467b3ff5796ff1bbe113a06a6e64/Midnight_in_Paris_Wow_5.mp3"
},
{
"movie": "The Haunting",
"year": 1999,
"release_date": "1999-07-23",
"director": "Jan de Bont",
"character": "Luke Sanderson",
"movie_duration": "01:52:37",
"timestamp": "00:41:34",
"full_line": "Wow, I sorta got screwed on the ol' bedroom selection.",
"current_wow_in_movie": 4,
"total_wows_in_movie": 5,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6Zu7ux0JYrUWk0UC8vxPtj/d0da8bfbad670655779a9921ac514759/The_Haunting_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/01C128tlGJ79vtlFEPc7V9/184759a9ca6fb1ab57114977afccb2ff/The_Haunting_Wow_4_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/3fR8AigFIp2I1vkSLRhzur/afb0c226daf7806bc9bd9c5e7b008fb4/The_Haunting_Wow_4_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/1OCimrvhXGGfffHqBKaqz7/52d16b12a2d1a8a264b09364afc4c87c/The_Haunting_Wow_4_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6bwt57tdhBCbhsXZ4i0pce/7f6debc7e52f80c78a618f19c8087985/The_Haunting_Wow_4_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/3yvd3DvmY0XUyqWPLUYLqp/1aabc0f7a6b58003ccdaa61469b8d5ee/The_Haunting_Wow_4.mp3"
},
{
"movie": "Cars 3",
"year": 2017,
"release_date": "2017-05-23",
"director": "Brian Fee",
"character": "Lighting McQueen",
"movie_duration": "01:42:25",
"timestamp": "00:26:23",
"full_line": "Wow.",
"current_wow_in_movie": 5,
"total_wows_in_movie": 10,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/43fOBsgY8iOJL0dijvFnfl/ea361efc5131a859c173ab5dd3fdfe1e/Cars_3_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/4Vp8pVwekVrXfmHT3xYCBm/5775501444824d3ee90acda0698e3472/Cars_3_Wow_5_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/6IoA0jwJiPwyXcSbDCrbJ5/5e65c8caa57c62ce9fc862aaeb327255/Cars_3_Wow_5_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/JrOrzMzr2aHCVPkRJUCae/06c5cb7543e95211a6f99ed89e6ea498/Cars_3_Wow_5_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6uufhJa3yX9e0Ib0xsOb46/16f9e55246ad32a33a34d58e621b8942/Cars_3_Wow_5_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/4aUtZzrqLHol2Hhb52zgHQ/ed5c4ef03ebba9ae34659e9058e58461/Cars_3_Wow_5.mp3"
},
{
"movie": "Cars 3",
"year": 2017,
"release_date": "2017-05-23",
"director": "Brian Fee",
"character": "Lighting McQueen",
"movie_duration": "01:42:25",
"timestamp": "00:26:11",
"full_line": "Wow.",
"current_wow_in_movie": 4,
"total_wows_in_movie": 10,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/43fOBsgY8iOJL0dijvFnfl/ea361efc5131a859c173ab5dd3fdfe1e/Cars_3_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/7G6jLS5xfYBOepUxkW7R3c/c78d22f63ba51f371a1550834888b9ca/Cars_3_Wow_4_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/lIhPcmNS5L4DnpY41EpUA/96b0c5b44acf3fe16e68d1e67156d41c/Cars_3_Wow_4_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/1h3am3BfJYUm0VXV4uKF9P/e75775ec0621889efd40ce1bc372735a/Cars_3_Wow_4_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6eO8c3ojQA4rWMlE1hMMOa/c3a9ce4c01b2d342b33144c9f90b9e3e/Cars_3_Wow_4_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/6aJuGg3bTjqd20j59vP1Wv/6cb60311194d3a9aa040882911a5f516/Cars_3_Wow_4.mp3"
},
{
"movie": "Midnight in Paris",
"year": 2011,
"release_date": "2011-05-20",
"director": "Woody Allen",
"character": "Gil Pender",
"movie_duration": "01:33:57",
"timestamp": "01:19:23",
"full_line": "Wow. Yes. Yes. Yes.",
"current_wow_in_movie": 7,
"total_wows_in_movie": 10,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/2ZcfSCe2dlfoVzYMr4b9nK/d566e5ad044dee56645f3bffc7200d64/Midnight_in_Paris_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/7N21xMDnGKfrmBO42xvoc9/c8e05e53e5841c6ba8a659aaf4f6736a/Midnight_in_Paris_Wow_7_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/6CF2q8U9OYgt3yFA7JUBkr/d6ddbf8d57b1cf9d38127735a6266431/Midnight_in_Paris_Wow_7_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/4IoMNf4pF7L3wDZ72Ad31d/efd2e6859fecf3a82a7ecdaf43175826/Midnight_in_Paris_Wow_7_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/5yF8k9rwFj99H69WASEZWU/f9741ed0771da2afd9a26454863137bb/Midnight_in_Paris_Wow_7_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/UmpPa6skALBubhqeKQFpn/2a64c51d16877b8c0bf8c23a74749f7e/Midnight_in_Paris_Wow_7.mp3"
},
{
"movie": "Midnight in Paris",
"year": 2011,
"release_date": "2011-05-20",
"director": "Woody Allen",
"character": "Gil Pender",
"movie_duration": "01:33:57",
"timestamp": "00:48:45",
"full_line": "Wow.",
"current_wow_in_movie": 3,
"total_wows_in_movie": 10,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/2ZcfSCe2dlfoVzYMr4b9nK/d566e5ad044dee56645f3bffc7200d64/Midnight_in_Paris_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/7BBJiej0qdBbuB3Xvimrae/932bc77c9e9a9918949709f846035541/Midnight_in_Paris_Wow_3_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/5tBiVUM6ef2mARH3OXzP92/8ad999e82b7bff5ac4a07d1b4dcb45f3/Midnight_in_Paris_Wow_3_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/39zl8hKK4QP1kASldccYyN/7fc8a7c86872abb9fd527a350365beea/Midnight_in_Paris_Wow_3_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/6rl512MqIH6r04L4O9jHU2/2d843c19937d770860f17719960d8352/Midnight_in_Paris_Wow_3_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/7BDkqWADSOxxYOSQGqNRcr/6fc4696de0d8bcafa487ddea97bb6d3b/Midnight_in_Paris_Wow_3.mp3"
},
{
"movie": "The Internship",
"year": 2013,
"release_date": "2013-05-29",
"director": "Shawn Levy",
"character": "Nick Campbell",
"movie_duration": "02:05:02",
"timestamp": "01:27:38",
"full_line": "Wow, a little heart and everything.",
"current_wow_in_movie": 5,
"total_wows_in_movie": 5,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/6XhmTpc1PoiTf0q1nDYMyv/594947f72b4dba7f3c24938a680dd603/The_Internship_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/1tZ97B7BWV7WhuYJSRL0aQ/c86ca6ce4c67a0f1f5343e68a7b1f428/The_Internship_Wow_5_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/2QlKc3s0Nf10vMLaKGFhVf/a76e1c99d80b13687ae593ad95837706/The_Internship_Wow_5_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/2t0rkVxOB7MVJVzUtVobAV/c396fd523e190052d4b009081b22423f/The_Internship_Wow_5_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/1W9V229ebo4J74HLZGO7pF/f4379d501080fc77221ca8df020a7cd6/The_Internship_Wow_5_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/30nYCeovpGBN5dwVmnTxrf/62c07aaab901bb488bc53ed61d2edffc/The_Internship_Wow_5.mp3"
},
{
"movie": "The Big Year",
"year": 2011,
"release_date": "2011-10-14",
"director": "David Frankel",
"character": "Kenny Bostick",
"movie_duration": "01:43:09",
"timestamp": "00:44:48",
"full_line": "Wow!",
"current_wow_in_movie": 1,
"total_wows_in_movie": 3,
"poster": "https://images.ctfassets.net/bs8ntwkklfua/pCjGOhbTCQVjLRN9zTwIi/ce7cdf4b40f3549326d881697aa468a1/The_Big_Year_Poster.jpg",
"video": {
"1080p": "https://videos.ctfassets.net/bs8ntwkklfua/2IZMW5Aeytz5rtu5MzcFk8/f675c3f6ef153c5df0c81679c80677d4/The_Big_Year_Wow_1_1080p.mp4",
"720p": "https://videos.ctfassets.net/bs8ntwkklfua/2K0XjRiHYd8zbdYcmiTMH4/b2e4a9b02db184a4d4bd71fe15ab37a9/The_Big_Year_Wow_1_720p.mp4",
"480p": "https://videos.ctfassets.net/bs8ntwkklfua/6QMkzBk6HrfuVxVT97mQg/5877904b163d7ccdc4baa92d449858d8/The_Big_Year_Wow_1_480p.mp4",
"360p": "https://videos.ctfassets.net/bs8ntwkklfua/5SFeCoTmyTUEJYtK0kOO92/462afffbd6315182db59271f99a5a829/The_Big_Year_Wow_1_360p.mp4"
},
"audio": "https://assets.ctfassets.net/bs8ntwkklfua/45tt9xH4Uf3Rgt0EJtykZZ/b5cef0c5d09d368359f4a9c0e66a6663/The_Big_Year_Wow_1.mp3"
}
]
+936
View File
@@ -0,0 +1,936 @@
{
"abilities": [
{
"ability": {
"name": "limber",
"url": "https://pokeapi.co/api/v2/ability/7/"
},
"is_hidden": false,
"slot": 1
},
{
"ability": {
"name": "imposter",
"url": "https://pokeapi.co/api/v2/ability/150/"
},
"is_hidden": true,
"slot": 3
}
],
"base_experience": 101,
"forms": [
{
"name": "ditto",
"url": "https://pokeapi.co/api/v2/pokemon-form/132/"
}
],
"game_indices": [
{
"game_index": 76,
"version": {
"name": "red",
"url": "https://pokeapi.co/api/v2/version/1/"
}
},
{
"game_index": 76,
"version": {
"name": "blue",
"url": "https://pokeapi.co/api/v2/version/2/"
}
},
{
"game_index": 76,
"version": {
"name": "yellow",
"url": "https://pokeapi.co/api/v2/version/3/"
}
},
{
"game_index": 132,
"version": {
"name": "gold",
"url": "https://pokeapi.co/api/v2/version/4/"
}
},
{
"game_index": 132,
"version": {
"name": "silver",
"url": "https://pokeapi.co/api/v2/version/5/"
}
},
{
"game_index": 132,
"version": {
"name": "crystal",
"url": "https://pokeapi.co/api/v2/version/6/"
}
},
{
"game_index": 132,
"version": {
"name": "ruby",
"url": "https://pokeapi.co/api/v2/version/7/"
}
},
{
"game_index": 132,
"version": {
"name": "sapphire",
"url": "https://pokeapi.co/api/v2/version/8/"
}
},
{
"game_index": 132,
"version": {
"name": "emerald",
"url": "https://pokeapi.co/api/v2/version/9/"
}
},
{
"game_index": 132,
"version": {
"name": "firered",
"url": "https://pokeapi.co/api/v2/version/10/"
}
},
{
"game_index": 132,
"version": {
"name": "leafgreen",
"url": "https://pokeapi.co/api/v2/version/11/"
}
},
{
"game_index": 132,
"version": {
"name": "diamond",
"url": "https://pokeapi.co/api/v2/version/12/"
}
},
{
"game_index": 132,
"version": {
"name": "pearl",
"url": "https://pokeapi.co/api/v2/version/13/"
}
},
{
"game_index": 132,
"version": {
"name": "platinum",
"url": "https://pokeapi.co/api/v2/version/14/"
}
},
{
"game_index": 132,
"version": {
"name": "heartgold",
"url": "https://pokeapi.co/api/v2/version/15/"
}
},
{
"game_index": 132,
"version": {
"name": "soulsilver",
"url": "https://pokeapi.co/api/v2/version/16/"
}
},
{
"game_index": 132,
"version": {
"name": "black",
"url": "https://pokeapi.co/api/v2/version/17/"
}
},
{
"game_index": 132,
"version": {
"name": "white",
"url": "https://pokeapi.co/api/v2/version/18/"
}
},
{
"game_index": 132,
"version": {
"name": "black-2",
"url": "https://pokeapi.co/api/v2/version/21/"
}
},
{
"game_index": 132,
"version": {
"name": "white-2",
"url": "https://pokeapi.co/api/v2/version/22/"
}
}
],
"height": 3,
"held_items": [
{
"item": {
"name": "metal-powder",
"url": "https://pokeapi.co/api/v2/item/234/"
},
"version_details": [
{
"rarity": 5,
"version": {
"name": "ruby",
"url": "https://pokeapi.co/api/v2/version/7/"
}
},
{
"rarity": 5,
"version": {
"name": "sapphire",
"url": "https://pokeapi.co/api/v2/version/8/"
}
},
{
"rarity": 5,
"version": {
"name": "emerald",
"url": "https://pokeapi.co/api/v2/version/9/"
}
},
{
"rarity": 5,
"version": {
"name": "firered",
"url": "https://pokeapi.co/api/v2/version/10/"
}
},
{
"rarity": 5,
"version": {
"name": "leafgreen",
"url": "https://pokeapi.co/api/v2/version/11/"
}
},
{
"rarity": 5,
"version": {
"name": "diamond",
"url": "https://pokeapi.co/api/v2/version/12/"
}
},
{
"rarity": 5,
"version": {
"name": "pearl",
"url": "https://pokeapi.co/api/v2/version/13/"
}
},
{
"rarity": 5,
"version": {
"name": "platinum",
"url": "https://pokeapi.co/api/v2/version/14/"
}
},
{
"rarity": 5,
"version": {
"name": "heartgold",
"url": "https://pokeapi.co/api/v2/version/15/"
}
},
{
"rarity": 5,
"version": {
"name": "soulsilver",
"url": "https://pokeapi.co/api/v2/version/16/"
}
},
{
"rarity": 5,
"version": {
"name": "black",
"url": "https://pokeapi.co/api/v2/version/17/"
}
},
{
"rarity": 5,
"version": {
"name": "white",
"url": "https://pokeapi.co/api/v2/version/18/"
}
},
{
"rarity": 5,
"version": {
"name": "black-2",
"url": "https://pokeapi.co/api/v2/version/21/"
}
},
{
"rarity": 5,
"version": {
"name": "white-2",
"url": "https://pokeapi.co/api/v2/version/22/"
}
},
{
"rarity": 5,
"version": {
"name": "x",
"url": "https://pokeapi.co/api/v2/version/23/"
}
},
{
"rarity": 5,
"version": {
"name": "y",
"url": "https://pokeapi.co/api/v2/version/24/"
}
},
{
"rarity": 5,
"version": {
"name": "omega-ruby",
"url": "https://pokeapi.co/api/v2/version/25/"
}
},
{
"rarity": 5,
"version": {
"name": "alpha-sapphire",
"url": "https://pokeapi.co/api/v2/version/26/"
}
},
{
"rarity": 5,
"version": {
"name": "sun",
"url": "https://pokeapi.co/api/v2/version/27/"
}
},
{
"rarity": 5,
"version": {
"name": "moon",
"url": "https://pokeapi.co/api/v2/version/28/"
}
},
{
"rarity": 5,
"version": {
"name": "ultra-sun",
"url": "https://pokeapi.co/api/v2/version/29/"
}
},
{
"rarity": 5,
"version": {
"name": "ultra-moon",
"url": "https://pokeapi.co/api/v2/version/30/"
}
}
]
},
{
"item": {
"name": "quick-powder",
"url": "https://pokeapi.co/api/v2/item/251/"
},
"version_details": [
{
"rarity": 50,
"version": {
"name": "diamond",
"url": "https://pokeapi.co/api/v2/version/12/"
}
},
{
"rarity": 50,
"version": {
"name": "pearl",
"url": "https://pokeapi.co/api/v2/version/13/"
}
},
{
"rarity": 50,
"version": {
"name": "platinum",
"url": "https://pokeapi.co/api/v2/version/14/"
}
},
{
"rarity": 50,
"version": {
"name": "heartgold",
"url": "https://pokeapi.co/api/v2/version/15/"
}
},
{
"rarity": 50,
"version": {
"name": "soulsilver",
"url": "https://pokeapi.co/api/v2/version/16/"
}
},
{
"rarity": 50,
"version": {
"name": "black",
"url": "https://pokeapi.co/api/v2/version/17/"
}
},
{
"rarity": 50,
"version": {
"name": "white",
"url": "https://pokeapi.co/api/v2/version/18/"
}
},
{
"rarity": 50,
"version": {
"name": "black-2",
"url": "https://pokeapi.co/api/v2/version/21/"
}
},
{
"rarity": 50,
"version": {
"name": "white-2",
"url": "https://pokeapi.co/api/v2/version/22/"
}
},
{
"rarity": 50,
"version": {
"name": "x",
"url": "https://pokeapi.co/api/v2/version/23/"
}
},
{
"rarity": 50,
"version": {
"name": "y",
"url": "https://pokeapi.co/api/v2/version/24/"
}
},
{
"rarity": 50,
"version": {
"name": "omega-ruby",
"url": "https://pokeapi.co/api/v2/version/25/"
}
},
{
"rarity": 50,
"version": {
"name": "alpha-sapphire",
"url": "https://pokeapi.co/api/v2/version/26/"
}
},
{
"rarity": 50,
"version": {
"name": "sun",
"url": "https://pokeapi.co/api/v2/version/27/"
}
},
{
"rarity": 50,
"version": {
"name": "moon",
"url": "https://pokeapi.co/api/v2/version/28/"
}
},
{
"rarity": 50,
"version": {
"name": "ultra-sun",
"url": "https://pokeapi.co/api/v2/version/29/"
}
},
{
"rarity": 50,
"version": {
"name": "ultra-moon",
"url": "https://pokeapi.co/api/v2/version/30/"
}
}
]
}
],
"id": 132,
"is_default": true,
"location_area_encounters": "https://pokeapi.co/api/v2/pokemon/132/encounters",
"moves": [
{
"move": {
"name": "transform",
"url": "https://pokeapi.co/api/v2/move/144/"
},
"version_group_details": [
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "red-blue",
"url": "https://pokeapi.co/api/v2/version-group/1/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "yellow",
"url": "https://pokeapi.co/api/v2/version-group/2/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "gold-silver",
"url": "https://pokeapi.co/api/v2/version-group/3/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "crystal",
"url": "https://pokeapi.co/api/v2/version-group/4/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "ruby-sapphire",
"url": "https://pokeapi.co/api/v2/version-group/5/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "emerald",
"url": "https://pokeapi.co/api/v2/version-group/6/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "firered-leafgreen",
"url": "https://pokeapi.co/api/v2/version-group/7/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "diamond-pearl",
"url": "https://pokeapi.co/api/v2/version-group/8/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "platinum",
"url": "https://pokeapi.co/api/v2/version-group/9/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "heartgold-soulsilver",
"url": "https://pokeapi.co/api/v2/version-group/10/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "black-white",
"url": "https://pokeapi.co/api/v2/version-group/11/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "colosseum",
"url": "https://pokeapi.co/api/v2/version-group/12/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "xd",
"url": "https://pokeapi.co/api/v2/version-group/13/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "black-2-white-2",
"url": "https://pokeapi.co/api/v2/version-group/14/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "x-y",
"url": "https://pokeapi.co/api/v2/version-group/15/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "omega-ruby-alpha-sapphire",
"url": "https://pokeapi.co/api/v2/version-group/16/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "sun-moon",
"url": "https://pokeapi.co/api/v2/version-group/17/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "ultra-sun-ultra-moon",
"url": "https://pokeapi.co/api/v2/version-group/18/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "lets-go-pikachu-lets-go-eevee",
"url": "https://pokeapi.co/api/v2/version-group/19/"
}
},
{
"level_learned_at": 1,
"move_learn_method": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/move-learn-method/1/"
},
"version_group": {
"name": "sword-shield",
"url": "https://pokeapi.co/api/v2/version-group/20/"
}
}
]
}
],
"name": "ditto",
"order": 214,
"past_types": [],
"species": {
"name": "ditto",
"url": "https://pokeapi.co/api/v2/pokemon-species/132/"
},
"sprites": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/132.png",
"back_female": null,
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/back/shiny/132.png",
"back_shiny_female": null,
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/132.png",
"front_female": null,
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/132.png",
"front_shiny_female": null,
"other": {
"dream_world": {
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/dream-world/132.svg",
"front_female": null
},
"home": {
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/home/132.png",
"front_female": null,
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/home/shiny/132.png",
"front_shiny_female": null
},
"official-artwork": {
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/132.png"
}
},
"versions": {
"generation-i": {
"red-blue": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/back/132.png",
"back_gray": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/back/gray/132.png",
"back_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/transparent/back/132.png",
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/132.png",
"front_gray": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/gray/132.png",
"front_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/red-blue/transparent/132.png"
},
"yellow": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/back/132.png",
"back_gray": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/back/gray/132.png",
"back_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/transparent/back/132.png",
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/132.png",
"front_gray": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/gray/132.png",
"front_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-i/yellow/transparent/132.png"
}
},
"generation-ii": {
"crystal": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/back/132.png",
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/back/shiny/132.png",
"back_shiny_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/transparent/back/shiny/132.png",
"back_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/transparent/back/132.png",
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/132.png",
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/shiny/132.png",
"front_shiny_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/transparent/shiny/132.png",
"front_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/crystal/transparent/132.png"
},
"gold": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/gold/back/132.png",
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/gold/back/shiny/132.png",
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/gold/132.png",
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/gold/shiny/132.png",
"front_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/gold/transparent/132.png"
},
"silver": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/silver/back/132.png",
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/silver/back/shiny/132.png",
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/silver/132.png",
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/silver/shiny/132.png",
"front_transparent": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-ii/silver/transparent/132.png"
}
},
"generation-iii": {
"emerald": {
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/emerald/132.png",
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/emerald/shiny/132.png"
},
"firered-leafgreen": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/firered-leafgreen/back/132.png",
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/firered-leafgreen/back/shiny/132.png",
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/firered-leafgreen/132.png",
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/firered-leafgreen/shiny/132.png"
},
"ruby-sapphire": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/ruby-sapphire/back/132.png",
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/ruby-sapphire/back/shiny/132.png",
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/ruby-sapphire/132.png",
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iii/ruby-sapphire/shiny/132.png"
}
},
"generation-iv": {
"diamond-pearl": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/diamond-pearl/back/132.png",
"back_female": null,
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/diamond-pearl/back/shiny/132.png",
"back_shiny_female": null,
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/diamond-pearl/132.png",
"front_female": null,
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/diamond-pearl/shiny/132.png",
"front_shiny_female": null
},
"heartgold-soulsilver": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/heartgold-soulsilver/back/132.png",
"back_female": null,
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/heartgold-soulsilver/back/shiny/132.png",
"back_shiny_female": null,
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/heartgold-soulsilver/132.png",
"front_female": null,
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/heartgold-soulsilver/shiny/132.png",
"front_shiny_female": null
},
"platinum": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/platinum/back/132.png",
"back_female": null,
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/platinum/back/shiny/132.png",
"back_shiny_female": null,
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/platinum/132.png",
"front_female": null,
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-iv/platinum/shiny/132.png",
"front_shiny_female": null
}
},
"generation-v": {
"black-white": {
"animated": {
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/animated/back/132.gif",
"back_female": null,
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/animated/back/shiny/132.gif",
"back_shiny_female": null,
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/animated/132.gif",
"front_female": null,
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/animated/shiny/132.gif",
"front_shiny_female": null
},
"back_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/back/132.png",
"back_female": null,
"back_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/back/shiny/132.png",
"back_shiny_female": null,
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/132.png",
"front_female": null,
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-v/black-white/shiny/132.png",
"front_shiny_female": null
}
},
"generation-vi": {
"omegaruby-alphasapphire": {
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vi/omegaruby-alphasapphire/132.png",
"front_female": null,
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vi/omegaruby-alphasapphire/shiny/132.png",
"front_shiny_female": null
},
"x-y": {
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vi/x-y/132.png",
"front_female": null,
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vi/x-y/shiny/132.png",
"front_shiny_female": null
}
},
"generation-vii": {
"icons": {
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vii/icons/132.png",
"front_female": null
},
"ultra-sun-ultra-moon": {
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vii/ultra-sun-ultra-moon/132.png",
"front_female": null,
"front_shiny": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-vii/ultra-sun-ultra-moon/shiny/132.png",
"front_shiny_female": null
}
},
"generation-viii": {
"icons": {
"front_default": "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/versions/generation-viii/icons/132.png",
"front_female": null
}
}
}
},
"stats": [
{
"base_stat": 48,
"effort": 1,
"stat": {
"name": "hp",
"url": "https://pokeapi.co/api/v2/stat/1/"
}
},
{
"base_stat": 48,
"effort": 0,
"stat": {
"name": "attack",
"url": "https://pokeapi.co/api/v2/stat/2/"
}
},
{
"base_stat": 48,
"effort": 0,
"stat": {
"name": "defense",
"url": "https://pokeapi.co/api/v2/stat/3/"
}
},
{
"base_stat": 48,
"effort": 0,
"stat": {
"name": "special-attack",
"url": "https://pokeapi.co/api/v2/stat/4/"
}
},
{
"base_stat": 48,
"effort": 0,
"stat": {
"name": "special-defense",
"url": "https://pokeapi.co/api/v2/stat/5/"
}
},
{
"base_stat": 48,
"effort": 0,
"stat": {
"name": "speed",
"url": "https://pokeapi.co/api/v2/stat/6/"
}
}
],
"types": [
{
"slot": 1,
"type": {
"name": "normal",
"url": "https://pokeapi.co/api/v2/type/1/"
}
}
],
"weight": 40
}
+22
View File
@@ -0,0 +1,22 @@
[
"There has never been a sadness that cant been cured by breakfast food.",
"Dear frozen yogurt, you are the celery of desserts. Be ice cream or be nothing. Zero stars.",
"Shorts over six inches are capri pants, shorts under six inches are European.",
"Sting like a bee. Do not float like a butterfly. Thats ridiculous.",
"Well, I am not usually one for speeches. So, goodbye.",
"I change my locks every 16 days.",
"Are you going to tell a man that he can't fart in his own car?",
"I love nothing.",
"Fishing relaxes me. It's like yoga, except I still get to kill something.",
"My son is several weeks old. He is very familiar with the sound of power tools.",
"Do you have any history of mental illness in your family? I have an uncle who does yoga.",
"If there were more food and fewer people, this would be a perfect party.",
"The three most useless jobs in the world in order are: lawyer, congressman, and doctor.",
"One rage every three months is permitted. Try not to hurt anyone who doesn't deserve it.",
"I hate everything.",
"Ive had the same haircut since 1978 and Ive driven the same car since 1991. Ive used the same wooden comb for three decades. I have one bowl. I still get my milk delivered by horse.",
"Tom put all my records into this rectangle!",
"Its pointless for a human to paint scenes of nature when they can go outside and stand in it.",
"My first ex-wifes name is Tammy. My second ex-wifes name is Tammy. My Moms name is Tamara…she goes by Tammy.",
"Live your life how you want, but dont confuse drama with happiness."
]
+216 -216
View File
@@ -56,7 +56,7 @@
"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 +1724,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 +1793,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 +1808,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 +1821,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 +1840,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 +1855,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 +1870,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 +1889,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 +1910,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 +1948,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 +1961,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 +2027,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"
@@ -4396,9 +4396,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 +10236,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 +10267,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 +10491,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 +11919,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 +14905,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 +14962,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 +15000,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 +15040,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 +15088,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": {}
}
@@ -17037,9 +17037,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 +21188,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 +21364,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 +22398,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": {
+1 -1
View File
@@ -76,7 +76,7 @@
"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",
+5 -3
View File
@@ -6,16 +6,18 @@ describe("formatStarCount", () => {
expect(formatStarCount(0)).toBe("0");
expect(formatStarCount(999)).toBe("999");
expect(formatStarCount(1000)).toBe("1k");
expect(formatStarCount(1050)).toBe("1.1k");
expect(formatStarCount(1100)).toBe("1.1k");
expect(formatStarCount(1200)).toBe("1.2k");
expect(formatStarCount(1300)).toBe("1.3k");
expect(formatStarCount(10000)).toBe("10k");
expect(formatStarCount(10050)).toBe("10.1k");
expect(formatStarCount(10100)).toBe("10.1k");
expect(formatStarCount(10101)).toBe("10.1k");
expect(formatStarCount(10199)).toBe("10.1k");
expect(formatStarCount(10199)).toBe("10.2k");
expect(formatStarCount(10200)).toBe("10.2k");
expect(formatStarCount(52678)).toBe("52.6k");
expect(formatStarCount(99999)).toBe("99.9k");
expect(formatStarCount(52678)).toBe("52.7k");
expect(formatStarCount(99949)).toBe("99.9k");
expect(formatStarCount(100000)).toBe("100k");
expect(formatStarCount(100100)).toBe("100.1k");
expect(formatStarCount(101100)).toBe("101.1k");
+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"],
},
]);