mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-06-27 17:45:41 -04:00
re-enable comments on non-post pages
This commit is contained in:
103
.github/copilot-instructions.md
vendored
Normal file
103
.github/copilot-instructions.md
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
# Copilot Instructions
|
||||
|
||||
This file provides guidance to GitHub Copilot when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
This is a personal website (jarv.is) built with Next.js, TypeScript, and various modern web technologies. The site uses the Next.js App Router and is designed to be deployed on Vercel. It includes features like blog posts (notes), projects showcase, contact form, and hit counter API.
|
||||
|
||||
## Development Commands
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Start development server
|
||||
pnpm dev
|
||||
|
||||
# Build for production
|
||||
pnpm build
|
||||
|
||||
# Start production server
|
||||
pnpm start
|
||||
|
||||
# Lint code
|
||||
pnpm lint
|
||||
|
||||
# Type check
|
||||
pnpm typecheck
|
||||
|
||||
# Database migrations (using Drizzle)
|
||||
npx drizzle-kit generate
|
||||
```
|
||||
|
||||
## Environment Setup
|
||||
|
||||
The project requires several environment variables to function properly. Copy `.env.example` to a new `.env` file and populate the required values. The environment variables are documented and type-checked in `lib/env.ts`.
|
||||
|
||||
Required server environment variables:
|
||||
|
||||
- `AUTH_SECRET`: Random value for authentication encryption
|
||||
- `AUTH_GITHUB_CLIENT_ID`: Client ID from GitHub OAuth App
|
||||
- `AUTH_GITHUB_CLIENT_SECRET`: Client secret from GitHub OAuth App
|
||||
- `DATABASE_URL`: PostgreSQL connection string (Neon)
|
||||
- `GITHUB_TOKEN`: GitHub API token for projects page
|
||||
- `RESEND_API_KEY`: Resend API key for contact form
|
||||
- `RESEND_TO_EMAIL`: Destination email for contact form
|
||||
- `TURNSTILE_SECRET_KEY`: Cloudflare Turnstile secret key
|
||||
|
||||
Required client environment variables:
|
||||
|
||||
- `NEXT_PUBLIC_GITHUB_REPO`: Repository in format "username/repo"
|
||||
- `NEXT_PUBLIC_GITHUB_USERNAME`: GitHub username
|
||||
- `NEXT_PUBLIC_TURNSTILE_SITE_KEY`: Cloudflare Turnstile site key
|
||||
|
||||
## Architecture
|
||||
|
||||
### Core Technologies
|
||||
|
||||
- **Next.js App Router**: Modern React framework with server components
|
||||
- **TypeScript**: Type safety throughout the project
|
||||
- **Tailwind CSS**: Styling with utility classes
|
||||
- **Drizzle ORM**: Database interactions with type safety
|
||||
- **Better Auth**: Authentication system
|
||||
- **MDX**: For notes/blog content with enhanced features
|
||||
- **Neon PostgreSQL**: Serverless database
|
||||
|
||||
### Database Schema
|
||||
|
||||
The database schema is defined in `lib/db/schema.ts` and includes tables for:
|
||||
|
||||
- User accounts and sessions (auth system)
|
||||
- Pages (for hit counter)
|
||||
- Comments system
|
||||
|
||||
### Content Structure
|
||||
|
||||
- `/app`: Next.js App Router pages and layouts
|
||||
- `/components`: React components organized by feature
|
||||
- `/lib`: Utility functions and configurations
|
||||
- `/notes`: MDX content for blog posts
|
||||
- `/public`: Static assets
|
||||
|
||||
### Important Features
|
||||
|
||||
1. **Authentication**: GitHub OAuth integration via Better Auth
|
||||
2. **MDX Processing**: Custom rehype/remark plugins for enhanced content
|
||||
3. **Comments System**: GitHub-authenticated commenting system
|
||||
4. **Hit Counter**: Simple analytics for page views
|
||||
5. **Contact Form**: With Cloudflare Turnstile protection
|
||||
|
||||
## Development Considerations
|
||||
|
||||
1. The project assumes deployment to Vercel and makes use of Vercel-specific features
|
||||
|
||||
2. When working with MDX content, note the custom plugins and transformations in `next.config.ts`
|
||||
|
||||
3. Database operations use Drizzle ORM with Neon's serverless PostgreSQL client
|
||||
|
||||
4. The repository uses strict linting and type checking through ESLint and TypeScript
|
||||
|
||||
5. React components follow patterns from shadcn/ui style system
|
||||
|
||||
6. Always prefer React Server Components (RSC) over client components, and server actions ("use server") over API routes
|
@ -1,6 +1,6 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { unstable_cache as cache } from "next/cache";
|
||||
import { getViews as _getViews } from "@/lib/server/views";
|
||||
import { getViews as _getViews } from "@/lib/views";
|
||||
|
||||
const getViews = cache(_getViews, undefined, {
|
||||
revalidate: 300, // 5 minutes
|
||||
|
@ -1,4 +1,7 @@
|
||||
import { Suspense } from "react";
|
||||
import PageTitle from "@/components/layout/page-title";
|
||||
import Comments from "@/components/comments/comments";
|
||||
import CommentsSkeleton from "@/components/comments/comments-skeleton";
|
||||
import { createMetadata } from "@/lib/metadata";
|
||||
|
||||
export const metadata = createMetadata({
|
||||
@ -7,6 +10,8 @@ export const metadata = createMetadata({
|
||||
canonical: "/cli",
|
||||
});
|
||||
|
||||
export const experimental_ppr = true;
|
||||
|
||||
<PageTitle canonical="/cli">CLI</PageTitle>
|
||||
|
||||
> The [Jake Jarvis](https://jarv.is/) CLI (aka the most useless Node module ever published, in history, by anyone, ever).
|
||||
@ -34,3 +39,7 @@ npx @jakejarvis/cli
|
||||
## License
|
||||
|
||||
MIT © [Jake Jarvis](https://jarv.is/), [Sindre Sorhus](https://sindresorhus.com/)
|
||||
|
||||
<Suspense fallback={<CommentsSkeleton />}>
|
||||
<Comments slug="uses" />
|
||||
</Suspense>
|
||||
|
@ -3,9 +3,8 @@ import path from "path";
|
||||
import fs from "fs";
|
||||
import { ImageResponse } from "next/og";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getSlugs, getFrontMatter } from "@/lib/posts";
|
||||
import { getSlugs, getFrontMatter, POSTS_DIR } from "@/lib/posts";
|
||||
import siteConfig from "@/lib/config/site";
|
||||
import { POSTS_DIR } from "@/lib/config/constants";
|
||||
|
||||
export const contentType = "image/png";
|
||||
export const size = {
|
||||
|
@ -7,11 +7,10 @@ import Link from "@/components/link";
|
||||
import ViewCounter from "@/components/view-counter";
|
||||
import Comments from "@/components/comments/comments";
|
||||
import CommentsSkeleton from "@/components/comments/comments-skeleton";
|
||||
import { getSlugs, getFrontMatter } from "@/lib/posts";
|
||||
import { getSlugs, getFrontMatter, POSTS_DIR } from "@/lib/posts";
|
||||
import { createMetadata } from "@/lib/metadata";
|
||||
import siteConfig from "@/lib/config/site";
|
||||
import authorConfig from "@/lib/config/author";
|
||||
import { POSTS_DIR } from "@/lib/config/constants";
|
||||
import { size as ogImageSize } from "./opengraph-image";
|
||||
import type { Metadata } from "next";
|
||||
import type { BlogPosting } from "schema-dts";
|
||||
@ -143,13 +142,9 @@ const Page = async ({ params }: { params: Promise<{ slug: string }> }) => {
|
||||
|
||||
<MDXContent />
|
||||
|
||||
<section id="comments" className="isolate mt-8 mb-10 min-h-36 w-full border-t-2 pt-8">
|
||||
<div className="mx-auto w-full max-w-3xl">
|
||||
<Suspense fallback={<CommentsSkeleton />}>
|
||||
<Comments slug={`${POSTS_DIR}/${frontmatter!.slug}`} closed={frontmatter!.noComments} />
|
||||
</Suspense>
|
||||
</div>
|
||||
</section>
|
||||
<Suspense fallback={<CommentsSkeleton />}>
|
||||
<Comments slug={`${POSTS_DIR}/${frontmatter!.slug}`} closed={frontmatter!.noComments} />
|
||||
</Suspense>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,16 +1,15 @@
|
||||
import { env } from "@/lib/env";
|
||||
import { EyeIcon } from "lucide-react";
|
||||
import Link from "@/components/link";
|
||||
import { getFrontMatter } from "@/lib/posts";
|
||||
import { getFrontMatter, POSTS_DIR } from "@/lib/posts";
|
||||
import { createMetadata } from "@/lib/metadata";
|
||||
import { formatDate, formatDateISO } from "@/lib/date";
|
||||
import authorConfig from "@/lib/config/author";
|
||||
import { POSTS_DIR } from "@/lib/config/constants";
|
||||
import { getViews } from "@/lib/server/views";
|
||||
import { getViews } from "@/lib/views";
|
||||
import type { ReactElement } from "react";
|
||||
import type { FrontMatter } from "@/lib/posts";
|
||||
|
||||
export const revalidate = 600; // 10 minutes
|
||||
export const revalidate = 300; // 5 minutes
|
||||
|
||||
export const metadata = createMetadata({
|
||||
title: "Notes",
|
||||
|
@ -21,7 +21,7 @@ export const getContributions = async (): Promise<
|
||||
},
|
||||
cache: "force-cache",
|
||||
next: {
|
||||
revalidate: 3600, // 1 hour
|
||||
revalidate: 900, // 15 minutes
|
||||
tags: ["github-contributions"],
|
||||
},
|
||||
});
|
||||
@ -126,7 +126,7 @@ export const getRepos = async (): Promise<Repository[] | undefined> => {
|
||||
...options,
|
||||
cache: "force-cache",
|
||||
next: {
|
||||
revalidate: 3600, // 1 hour
|
||||
revalidate: 900, // 15 minutes
|
||||
tags: ["github-repos"],
|
||||
},
|
||||
});
|
@ -9,7 +9,7 @@ import ActivityCalendar from "@/components/activity-calendar";
|
||||
import { GitHubIcon } from "@/components/icons";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { createMetadata } from "@/lib/metadata";
|
||||
import { getContributions, getRepos } from "@/lib/server/github";
|
||||
import { getContributions, getRepos } from "./github";
|
||||
|
||||
export const metadata = createMetadata({
|
||||
title: "Projects",
|
||||
|
@ -1,4 +1,7 @@
|
||||
import { Suspense } from "react";
|
||||
import PageTitle from "@/components/layout/page-title";
|
||||
import Comments from "@/components/comments/comments";
|
||||
import CommentsSkeleton from "@/components/comments/comments-skeleton";
|
||||
import { createMetadata } from "@/lib/metadata";
|
||||
|
||||
export const metadata = createMetadata({
|
||||
@ -7,6 +10,8 @@ export const metadata = createMetadata({
|
||||
canonical: "/uses",
|
||||
});
|
||||
|
||||
export const experimental_ppr = true;
|
||||
|
||||
<PageTitle canonical="/uses">Uses</PageTitle>
|
||||
|
||||
~~I regularly get messages asking about which tools I use to work.~~
|
||||
@ -164,3 +169,7 @@ Other geeky stuff:
|
||||
- 2x [**ecobee3 lite**](https://www.ecobee.com/en-us/smart-thermostats/smart-wifi-thermostat/)
|
||||
- 2x [**Sonos One**](https://www.sonos.com/en-us/shop/one.html) (with Alexa turned off...hopefully? 🤫)
|
||||
- 2x [**Apple TV 4K** (2021)](https://www.apple.com/apple-tv-4k/)
|
||||
|
||||
<Suspense fallback={<CommentsSkeleton />}>
|
||||
<Comments slug="uses" />
|
||||
</Suspense>
|
||||
|
@ -1,4 +1,7 @@
|
||||
import { Suspense } from "react";
|
||||
import PageTitle from "@/components/layout/page-title";
|
||||
import Comments from "@/components/comments/comments";
|
||||
import CommentsSkeleton from "@/components/comments/comments-skeleton";
|
||||
import { createMetadata } from "@/lib/metadata";
|
||||
|
||||
import backgroundImg from "./sundar.jpg";
|
||||
@ -9,6 +12,8 @@ export const metadata = createMetadata({
|
||||
canonical: "/zip",
|
||||
});
|
||||
|
||||
export const experimental_ppr = true;
|
||||
|
||||
export const Terminal = () => (
|
||||
<div
|
||||
className="relative mx-auto my-6 w-full rounded-lg"
|
||||
@ -71,3 +76,7 @@ A little-known monopolistic internet conglomorate simply unleashed [multiple](ht
|
||||
- **Kaspersky:** [Beware the .zip and .mov domains!](https://usa.kaspersky.com/blog/zip-mov-domain-extension-confusion/28351/)
|
||||
- **Palo Alto Networks:** [New Top Level Domains .zip and .mov open the door for new attacks](https://knowledgebase.paloaltonetworks.com/KCSArticleDetail?id=kA14u000000g1wOCAQ)
|
||||
- **Google, twenty years ago:** ["Don't be evil"](https://web.archive.org/web/20050204181615/http://investor.google.com/conduct.html)
|
||||
|
||||
<Suspense fallback={<CommentsSkeleton />}>
|
||||
<Comments slug="zip" />
|
||||
</Suspense>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import Skeleton from "@/components/ui/skeleton";
|
||||
import Wrapper from "./comments-wrapper";
|
||||
|
||||
const CommentsSkeleton = () => {
|
||||
return (
|
||||
<div className="mx-auto max-w-3xl space-y-6">
|
||||
<Wrapper>
|
||||
<Skeleton className="h-32 w-full" />
|
||||
|
||||
<div className="flex gap-4">
|
||||
@ -19,7 +20,7 @@ const CommentsSkeleton = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
11
components/comments/comments-wrapper.tsx
Normal file
11
components/comments/comments-wrapper.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const CommentsWrapper = ({ className, children }: { className?: string; children: React.ReactNode }) => {
|
||||
return (
|
||||
<section id="comments" className={cn("isolate mt-8 mb-10 min-h-36 w-full border-t-2 pt-8", className)}>
|
||||
<div className="mx-auto w-full max-w-3xl space-y-6 text-base leading-normal [&_p]:my-auto">{children}</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default CommentsWrapper;
|
@ -1,4 +1,5 @@
|
||||
import { headers } from "next/headers";
|
||||
import Wrapper from "./comments-wrapper";
|
||||
import Form from "./comment-form";
|
||||
import Thread from "./comment-thread";
|
||||
import SignIn from "./sign-in";
|
||||
@ -27,14 +28,14 @@ const Comments = async ({ slug, closed = false }: { slug: string; closed?: boole
|
||||
const rootComments = commentsByParentId["root"] || [];
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<Wrapper>
|
||||
{closed ? (
|
||||
<div className="bg-muted/40 flex min-h-32 items-center justify-center rounded-lg p-6">
|
||||
<p className="text-center font-medium">Comments are closed for this post.</p>
|
||||
</div>
|
||||
) : !session ? (
|
||||
<div className="bg-muted/40 flex flex-col items-center justify-center rounded-lg p-6">
|
||||
<p className="mb-4 text-center font-medium">Join the discussion by signing in:</p>
|
||||
<div className="bg-muted/40 flex flex-col items-center justify-center gap-y-4 rounded-lg p-6">
|
||||
<p className="text-center font-medium">Join the discussion by signing in:</p>
|
||||
<SignIn callbackPath={`/${slug}#comments`} />
|
||||
</div>
|
||||
) : (
|
||||
@ -57,7 +58,7 @@ const Comments = async ({ slug, closed = false }: { slug: string; closed?: boole
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { env } from "@/lib/env";
|
||||
import { connection } from "next/server";
|
||||
import CountUp from "@/components/count-up";
|
||||
import { incrementViews } from "@/lib/server/views";
|
||||
import { incrementViews } from "@/lib/views";
|
||||
|
||||
const ViewCounter = async ({ slug }: { slug: string }) => {
|
||||
// ensure this component isn't triggered by prerenders and/or preloads
|
||||
|
@ -1,2 +0,0 @@
|
||||
/** Path to directory with .mdx files, relative to project root. */
|
||||
export const POSTS_DIR = "notes" as const;
|
@ -14,7 +14,6 @@ import {
|
||||
remarkStripMdxImportsExports,
|
||||
} from "@/lib/remark";
|
||||
import { rehypeSanitize, rehypeStringify } from "@/lib/rehype";
|
||||
import { POSTS_DIR } from "@/lib/config/constants";
|
||||
|
||||
export type FrontMatter = {
|
||||
slug: string;
|
||||
@ -28,6 +27,9 @@ export type FrontMatter = {
|
||||
noComments?: boolean;
|
||||
};
|
||||
|
||||
/** Path to directory with .mdx files, relative to project root. */
|
||||
export const POSTS_DIR = "notes" as const;
|
||||
|
||||
/** Use filesystem to get a simple list of all post slugs */
|
||||
export const getSlugs = cache(async (): Promise<string[]> => {
|
||||
// list all .mdx files in POSTS_DIR
|
||||
|
@ -1,6 +1,5 @@
|
||||
import "server-only";
|
||||
|
||||
import { cache } from "react";
|
||||
import { eq, inArray } from "drizzle-orm";
|
||||
import { db } from "@/lib/db";
|
||||
import { page } from "@/lib/db/schema";
|
||||
@ -43,43 +42,41 @@ export const getViews: {
|
||||
* Retrieves the numbers of views for ALL slugs
|
||||
*/
|
||||
(): Promise<Record<string, number>>;
|
||||
} = cache(
|
||||
async (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
slug?: any
|
||||
): // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Promise<any> => {
|
||||
try {
|
||||
// return one page
|
||||
if (typeof slug === "string") {
|
||||
const pages = await db.select().from(page).where(eq(page.slug, slug)).limit(1);
|
||||
return pages[0].views;
|
||||
}
|
||||
} = async (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
slug?: any
|
||||
): // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Promise<any> => {
|
||||
try {
|
||||
// return one page
|
||||
if (typeof slug === "string") {
|
||||
const pages = await db.select().from(page).where(eq(page.slug, slug)).limit(1);
|
||||
return pages[0].views;
|
||||
}
|
||||
|
||||
// return multiple pages
|
||||
if (Array.isArray(slug)) {
|
||||
const pages = await db.select().from(page).where(inArray(page.slug, slug));
|
||||
return pages.reduce(
|
||||
(acc, page, index) => {
|
||||
acc[slug[index]] = page.views;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, number | null>
|
||||
);
|
||||
}
|
||||
|
||||
// return ALL pages
|
||||
const pages = await db.select().from(page);
|
||||
// return multiple pages
|
||||
if (Array.isArray(slug)) {
|
||||
const pages = await db.select().from(page).where(inArray(page.slug, slug));
|
||||
return pages.reduce(
|
||||
(acc, page) => {
|
||||
acc[page.slug] = page.views;
|
||||
(acc, page, index) => {
|
||||
acc[slug[index]] = page.views;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, number>
|
||||
{} as Record<string, number | null>
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("[server/views] fatal error:", error);
|
||||
throw new Error("Failed to get views");
|
||||
}
|
||||
|
||||
// return ALL pages
|
||||
const pages = await db.select().from(page);
|
||||
return pages.reduce(
|
||||
(acc, page) => {
|
||||
acc[page.slug] = page.views;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, number>
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("[server/views] fatal error:", error);
|
||||
throw new Error("Failed to get views");
|
||||
}
|
||||
);
|
||||
};
|
@ -56,7 +56,7 @@
|
||||
"lucide-react": "0.511.0",
|
||||
"next": "15.4.0-canary.38",
|
||||
"react": "19.1.0",
|
||||
"react-activity-calendar": "^2.7.11",
|
||||
"react-activity-calendar": "^2.7.12",
|
||||
"react-countup": "^6.5.3",
|
||||
"react-dom": "19.1.0",
|
||||
"react-lite-youtube-embed": "^2.5.1",
|
||||
@ -89,7 +89,7 @@
|
||||
"tailwind-merge": "^3.3.0",
|
||||
"tailwindcss": "^4.1.7",
|
||||
"unified": "^11.0.5",
|
||||
"zod": "3.25.0-beta.20250516T005923"
|
||||
"zod": "3.24.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
|
31
pnpm-lock.yaml
generated
31
pnpm-lock.yaml
generated
@ -73,7 +73,7 @@ importers:
|
||||
version: 1.2.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@t3-oss/env-nextjs':
|
||||
specifier: ^0.13.4
|
||||
version: 0.13.4(arktype@2.1.20)(typescript@5.8.3)(valibot@1.1.0(typescript@5.8.3))(zod@3.25.0-beta.20250516T005923)
|
||||
version: 0.13.4(arktype@2.1.20)(typescript@5.8.3)(valibot@1.1.0(typescript@5.8.3))(zod@3.24.4)
|
||||
'@vercel/analytics':
|
||||
specifier: ^1.5.0
|
||||
version: 1.5.0(next@15.4.0-canary.38(@babel/core@7.26.10)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
|
||||
@ -123,8 +123,8 @@ importers:
|
||||
specifier: 19.1.0
|
||||
version: 19.1.0
|
||||
react-activity-calendar:
|
||||
specifier: ^2.7.11
|
||||
version: 2.7.11(react@19.1.0)
|
||||
specifier: ^2.7.12
|
||||
version: 2.7.12(react@19.1.0)
|
||||
react-countup:
|
||||
specifier: ^6.5.3
|
||||
version: 6.5.3(react@19.1.0)
|
||||
@ -222,8 +222,8 @@ importers:
|
||||
specifier: ^11.0.5
|
||||
version: 11.0.5
|
||||
zod:
|
||||
specifier: 3.25.0-beta.20250516T005923
|
||||
version: 3.25.0-beta.20250516T005923
|
||||
specifier: 3.24.4
|
||||
version: 3.24.4
|
||||
devDependencies:
|
||||
'@eslint/eslintrc':
|
||||
specifier: ^3.3.1
|
||||
@ -4069,8 +4069,8 @@ packages:
|
||||
queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
|
||||
react-activity-calendar@2.7.11:
|
||||
resolution: {integrity: sha512-JHJyvdYciBVPt1ZkE2pqnmg0ZMsmer09CXD1qWe2hpl3PyMosVqFOMZmDqjLxRWI6VD2ILH4RFk5dZCuWwnaPg==}
|
||||
react-activity-calendar@2.7.12:
|
||||
resolution: {integrity: sha512-OzVconQ5LA/uF2ZN3zDeWZb4UxjOmGr1ymaGCSEAMLSzwjzP7ojdyZs8DyV7jcV+rZ+lmwp6BTpBJqdW8ehXyw==}
|
||||
peerDependencies:
|
||||
react: ^18.0.0 || ^19.0.0
|
||||
|
||||
@ -4922,9 +4922,6 @@ packages:
|
||||
zod@3.24.4:
|
||||
resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==}
|
||||
|
||||
zod@3.25.0-beta.20250516T005923:
|
||||
resolution: {integrity: sha512-pWO2WHnFfmKl9X/AY55DGqiyArXkOSNDyLAotrpQzfsnLOCgzLDk1tZRfFyIqd68UaBk32gIsksYpCHzMXqZqg==}
|
||||
|
||||
zwitch@2.0.4:
|
||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||
|
||||
@ -6206,21 +6203,21 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@t3-oss/env-core@0.13.4(arktype@2.1.20)(typescript@5.8.3)(valibot@1.1.0(typescript@5.8.3))(zod@3.25.0-beta.20250516T005923)':
|
||||
'@t3-oss/env-core@0.13.4(arktype@2.1.20)(typescript@5.8.3)(valibot@1.1.0(typescript@5.8.3))(zod@3.24.4)':
|
||||
dependencies:
|
||||
arktype: 2.1.20
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
valibot: 1.1.0(typescript@5.8.3)
|
||||
zod: 3.25.0-beta.20250516T005923
|
||||
zod: 3.24.4
|
||||
|
||||
'@t3-oss/env-nextjs@0.13.4(arktype@2.1.20)(typescript@5.8.3)(valibot@1.1.0(typescript@5.8.3))(zod@3.25.0-beta.20250516T005923)':
|
||||
'@t3-oss/env-nextjs@0.13.4(arktype@2.1.20)(typescript@5.8.3)(valibot@1.1.0(typescript@5.8.3))(zod@3.24.4)':
|
||||
dependencies:
|
||||
'@t3-oss/env-core': 0.13.4(arktype@2.1.20)(typescript@5.8.3)(valibot@1.1.0(typescript@5.8.3))(zod@3.25.0-beta.20250516T005923)
|
||||
'@t3-oss/env-core': 0.13.4(arktype@2.1.20)(typescript@5.8.3)(valibot@1.1.0(typescript@5.8.3))(zod@3.24.4)
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
valibot: 1.1.0(typescript@5.8.3)
|
||||
zod: 3.25.0-beta.20250516T005923
|
||||
zod: 3.24.4
|
||||
transitivePeerDependencies:
|
||||
- arktype
|
||||
|
||||
@ -9008,7 +9005,7 @@ snapshots:
|
||||
|
||||
queue-microtask@1.2.3: {}
|
||||
|
||||
react-activity-calendar@2.7.11(react@19.1.0):
|
||||
react-activity-calendar@2.7.12(react@19.1.0):
|
||||
dependencies:
|
||||
date-fns: 4.1.0
|
||||
react: 19.1.0
|
||||
@ -10170,6 +10167,4 @@ snapshots:
|
||||
|
||||
zod@3.24.4: {}
|
||||
|
||||
zod@3.25.0-beta.20250516T005923: {}
|
||||
|
||||
zwitch@2.0.4: {}
|
||||
|
Reference in New Issue
Block a user