From 7a646d2b0c7b6a86b89005d54de75f7017db7f45 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Sun, 14 Sep 2025 21:12:02 +0500 Subject: [PATCH 01/14] Update pnpm-lock.yaml and package.json to include twoslash dependencies and enhance Next.js configuration - Added `fumadocs-twoslash` and `twoslash` dependencies in `package.json` for improved documentation support. - Updated `pnpm-lock.yaml` to reflect new versions and peer dependencies for `twoslash`. - Modified `next.config.ts` to include `twoslash` and `typescript` in `serverExternalPackages` for better server-side handling. --- apps/www/next.config.ts | 1 + apps/www/package.json | 6 ++-- pnpm-lock.yaml | 80 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/apps/www/next.config.ts b/apps/www/next.config.ts index ac293012b..baa1b44f0 100644 --- a/apps/www/next.config.ts +++ b/apps/www/next.config.ts @@ -6,6 +6,7 @@ export default withSentryConfig( createMDX()({ reactStrictMode: true, outputFileTracingRoot: path.join(__dirname, "../../"), + serverExternalPackages: ["typescript", "twoslash"], }), { // For all available options, see: diff --git a/apps/www/package.json b/apps/www/package.json index 6918a6fd6..a62583a27 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -11,6 +11,7 @@ "fix": "pnpm -w run fix" }, "dependencies": { + "@ark/util": "^0.49.0", "@icons-pack/react-simple-icons": "^13.7.0", "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slot": "^1.2.3", @@ -21,6 +22,7 @@ "clsx": "^2.1.1", "fumadocs-core": "15.7.10", "fumadocs-mdx": "11.9.0", + "fumadocs-twoslash": "^3.1.7", "fumadocs-ui": "15.7.10", "lucide-react": "^0.542.0", "next": "15.5.2", @@ -29,8 +31,8 @@ "rehype-github-alerts": "^4.1.1", "remark-gemoji": "^8.0.0", "tailwind-merge": "^3.3.1", - "@ark/util": "^0.49.0", - "tailwindcss-animate": "^1.0.7" + "tailwindcss-animate": "^1.0.7", + "twoslash": "^0.3.4" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f66097bbc..369d37dfc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -130,6 +130,9 @@ importers: fumadocs-mdx: specifier: 11.9.0 version: 11.9.0(fumadocs-core@15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1)(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.5)) + fumadocs-twoslash: + specifier: ^3.1.7 + version: 3.1.7(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(fumadocs-ui@15.7.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(tailwindcss@4.1.13))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.2) fumadocs-ui: specifier: 15.7.10 version: 15.7.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(tailwindcss@4.1.13) @@ -157,6 +160,9 @@ importers: tailwindcss-animate: specifier: ^1.0.7 version: 1.0.7(tailwindcss@4.1.13) + twoslash: + specifier: ^0.3.4 + version: 0.3.4(typescript@5.9.2) devDependencies: '@tailwindcss/postcss': specifier: ^4.1.13 @@ -1951,6 +1957,11 @@ packages: '@shikijs/transformers@3.12.2': resolution: {integrity: sha512-+z1aMq4N5RoNGY8i7qnTYmG2MBYzFmwkm/yOd6cjEI7OVzcldVvzQCfxU1YbIVgsyB0xHVc2jFe1JhgoXyUoSQ==} + '@shikijs/twoslash@3.12.2': + resolution: {integrity: sha512-JthKvEvyE/gbu3u693mhNhEO6GYP1vetrwgEfqTAsT/G9AJ6nf7g7JVqdTSs+axdfilGWzZKeYdjfyanu/v5AA==} + peerDependencies: + typescript: '>=5.5.0' + '@shikijs/types@3.12.2': resolution: {integrity: sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==} @@ -2199,6 +2210,11 @@ packages: resolution: {integrity: sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript/vfs@1.6.1': + resolution: {integrity: sha512-JwoxboBh7Oz1v38tPbkrZ62ZXNHAk9bJ7c9x0eI5zBfBnBYGhURdbnh7Z4smN/MV48Y5OCcZb58n972UtbazsA==} + peerDependencies: + typescript: '*' + '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -2913,6 +2929,16 @@ packages: vite: optional: true + fumadocs-twoslash@3.1.7: + resolution: {integrity: sha512-RHO1K6Sh8O8eS9TCQRv9C3ek/TZuUrUqMNtoKBx7D/D5L6OB3Skol+PTltHDzyIrmrHVRkO20tBlqyRxD3awUA==} + peerDependencies: + '@types/react': '*' + fumadocs-ui: ^15.0.0 + react: 18.x.x || 19.x.x + peerDependenciesMeta: + '@types/react': + optional: true + fumadocs-ui@15.7.10: resolution: {integrity: sha512-yGSCuRwFSiHFbVperUzSM+8aP7LbOzI3HoiX1ORDPI1DsuUE1nCyxHjnKsczZImhjEwOqJPf/gywZHAbiPTJkA==} peerDependencies: @@ -4360,6 +4386,14 @@ packages: resolution: {integrity: sha512-gxToHmi9oTBNB05UjUsrWf0OyN5ZXtD0apOarC1KIx232Vp3WimRNy3810QzeNSgyD5rsaIDXlxlbnOzlouo+w==} hasBin: true + twoslash-protocol@0.3.4: + resolution: {integrity: sha512-HHd7lzZNLUvjPzG/IE6js502gEzLC1x7HaO1up/f72d8G8ScWAs9Yfa97igelQRDl5h9tGcdFsRp+lNVre1EeQ==} + + twoslash@0.3.4: + resolution: {integrity: sha512-RtJURJlGRxrkJmTcZMjpr7jdYly1rfgpujJr1sBM9ch7SKVht/SjFk23IOAyvwT1NLCk+SJiMrvW4rIAUM2Wug==} + peerDependencies: + typescript: ^5.5.0 + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -6466,6 +6500,15 @@ snapshots: '@shikijs/core': 3.12.2 '@shikijs/types': 3.12.2 + '@shikijs/twoslash@3.12.2(typescript@5.9.2)': + dependencies: + '@shikijs/core': 3.12.2 + '@shikijs/types': 3.12.2 + twoslash: 0.3.4(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@shikijs/types@3.12.2': dependencies: '@shikijs/vscode-textmate': 10.0.2 @@ -6749,6 +6792,13 @@ snapshots: '@typescript-eslint/types': 8.43.0 eslint-visitor-keys: 4.2.1 + '@typescript/vfs@1.6.1(typescript@5.9.2)': + dependencies: + debug: 4.4.1 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@ungap/structured-clone@1.3.0': {} '@vitejs/plugin-react@5.0.2(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.5))': @@ -7516,6 +7566,26 @@ snapshots: transitivePeerDependencies: - supports-color + fumadocs-twoslash@3.1.7(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(fumadocs-ui@15.7.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(tailwindcss@4.1.13))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.2): + dependencies: + '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@shikijs/twoslash': 3.12.2(typescript@5.9.2) + fumadocs-ui: 15.7.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(tailwindcss@4.1.13) + mdast-util-from-markdown: 2.0.2 + mdast-util-gfm: 3.1.0 + mdast-util-to-hast: 13.2.0 + react: 19.1.1 + shiki: 3.12.2 + tailwind-merge: 3.3.1 + twoslash: 0.3.4(typescript@5.9.2) + optionalDependencies: + '@types/react': 19.1.12 + transitivePeerDependencies: + - '@types/react-dom' + - react-dom + - supports-color + - typescript + fumadocs-ui@15.7.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(tailwindcss@4.1.13): dependencies: '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) @@ -9334,6 +9404,16 @@ snapshots: turbo-windows-64: 2.5.6 turbo-windows-arm64: 2.5.6 + twoslash-protocol@0.3.4: {} + + twoslash@0.3.4(typescript@5.9.2): + dependencies: + '@typescript/vfs': 1.6.1(typescript@5.9.2) + twoslash-protocol: 0.3.4 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 From 1b73acb728e80ec2c8127712deb2a40b2aa3c929 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Sun, 14 Sep 2025 21:24:13 +0500 Subject: [PATCH 02/14] Update dependencies and enhance documentation features - Added `import-in-the-middle` dependency in `package.json` for improved module handling. - Updated `pnpm-lock.yaml` to include the new dependency version. - Enhanced `source.config.ts` to integrate `fumadocs-twoslash` for better code documentation support. - Included `twoslash.css` in global styles for consistent theming. - Modified documentation page to utilize `fumadocs-twoslash` for interactive code examples. --- apps/www/app/docs/[[...slug]]/page.tsx | 2 ++ apps/www/app/globals.css | 1 + apps/www/content/docs/quickstart.mdx | 2 +- apps/www/next.config.ts | 2 +- apps/www/package.json | 1 + apps/www/source.config.ts | 13 ++++++++++++- pnpm-lock.yaml | 3 +++ 7 files changed, 21 insertions(+), 3 deletions(-) diff --git a/apps/www/app/docs/[[...slug]]/page.tsx b/apps/www/app/docs/[[...slug]]/page.tsx index ac9cbac32..4faca04a1 100644 --- a/apps/www/app/docs/[[...slug]]/page.tsx +++ b/apps/www/app/docs/[[...slug]]/page.tsx @@ -1,3 +1,4 @@ +import * as Twoslash from "fumadocs-twoslash/ui"; import { Accordion, Accordions } from "fumadocs-ui/components/accordion"; import { CodeBlock, Pre } from "fumadocs-ui/components/codeblock"; import { Step, Steps } from "fumadocs-ui/components/steps"; @@ -55,6 +56,7 @@ export default async function Page(props: {
{props.children}
), + ...Twoslash, }} /> diff --git a/apps/www/app/globals.css b/apps/www/app/globals.css index f02b4e4df..96ad85d05 100644 --- a/apps/www/app/globals.css +++ b/apps/www/app/globals.css @@ -6,6 +6,7 @@ @import "./styles/theme/inline.css"; @import "./styles/components/github-alerts.css"; @import "./styles/base.css"; +@import "fumadocs-twoslash/twoslash.css"; @plugin "tailwindcss-animate"; @source '../node_modules/fumadocs-ui/dist/**/*.js'; diff --git a/apps/www/content/docs/quickstart.mdx b/apps/www/content/docs/quickstart.mdx index 34308eaa7..dad631ace 100644 --- a/apps/www/content/docs/quickstart.mdx +++ b/apps/www/content/docs/quickstart.mdx @@ -34,7 +34,7 @@ description: Let's get you started with a few simple steps Add a schema to make your environment variables **validated** and **typesafe**: - ```typescript title="config/env.ts" + ```typescript title="config/env.ts" twoslash import arkenv from 'arkenv'; export const env = arkenv({ diff --git a/apps/www/next.config.ts b/apps/www/next.config.ts index baa1b44f0..0b8179a99 100644 --- a/apps/www/next.config.ts +++ b/apps/www/next.config.ts @@ -12,7 +12,7 @@ export default withSentryConfig( // For all available options, see: // https://github.com/getsentry/sentry-webpack-plugin#options - org: process.env.SENTRY_ORG, + org: process.env.SENTRY_ORG, project: process.env.SENTRY_PROJECT, // Only print logs for uploading source maps in CI diff --git a/apps/www/package.json b/apps/www/package.json index a62583a27..4ceb36bfc 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -24,6 +24,7 @@ "fumadocs-mdx": "11.9.0", "fumadocs-twoslash": "^3.1.7", "fumadocs-ui": "15.7.10", + "import-in-the-middle": "^1.14.2", "lucide-react": "^0.542.0", "next": "15.5.2", "react": "^19.1.1", diff --git a/apps/www/source.config.ts b/apps/www/source.config.ts index e078b3b9d..d29f4df29 100644 --- a/apps/www/source.config.ts +++ b/apps/www/source.config.ts @@ -1,5 +1,6 @@ -import { remarkNpm } from "fumadocs-core/mdx-plugins"; +import { rehypeCodeDefaultOptions, remarkNpm } from "fumadocs-core/mdx-plugins"; import { defineConfig, defineDocs } from "fumadocs-mdx/config"; +import { transformerTwoslash } from "fumadocs-twoslash"; import { rehypeGithubAlerts } from "rehype-github-alerts"; import remarkGemoji from "remark-gemoji"; @@ -14,5 +15,15 @@ export default defineConfig({ mdxOptions: { rehypePlugins: [rehypeGithubAlerts], remarkPlugins: [remarkGemoji, remarkNpm], + rehypeCodeOptions: { + themes: { + light: "github-light", + dark: "github-dark", + }, + transformers: [ + ...(rehypeCodeDefaultOptions.transformers ?? []), + transformerTwoslash(), + ], + }, }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 369d37dfc..386a70f6e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -136,6 +136,9 @@ importers: fumadocs-ui: specifier: 15.7.10 version: 15.7.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(tailwindcss@4.1.13) + import-in-the-middle: + specifier: ^1.14.2 + version: 1.14.2 lucide-react: specifier: ^0.542.0 version: 0.542.0(react@19.1.1) From 030d0219ae6a304020810e46d4c74206ccd36ad8 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Sun, 14 Sep 2025 22:39:41 +0500 Subject: [PATCH 03/14] Update arkenv package and enhance error handling - Added `arkenv` as a workspace dependency in `package.json` for better local development. - Updated `pnpm-lock.yaml` to include the new `require-in-the-middle` dependency. - Exported `ArkEnvError` from `arkenv` for improved error handling in environment variable validation. - Modified `create-env.ts` documentation to clarify error throwing behavior. - Enhanced `source.config.ts` to utilize a file system types cache for `fumadocs-twoslash` transformers. --- .changeset/all-ghosts-worry.md | 11 +++++++++++ apps/playgrounds/node/index.ts | 4 ++-- apps/www/next.config.ts | 2 +- apps/www/package.json | 2 ++ apps/www/source.config.ts | 5 ++++- packages/arkenv/src/create-env.ts | 2 +- packages/arkenv/src/index.ts | 6 ++++++ pnpm-lock.yaml | 6 ++++++ 8 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 .changeset/all-ghosts-worry.md diff --git a/.changeset/all-ghosts-worry.md b/.changeset/all-ghosts-worry.md new file mode 100644 index 000000000..06c8008d5 --- /dev/null +++ b/.changeset/all-ghosts-worry.md @@ -0,0 +1,11 @@ +--- +"arkenv": patch +--- + +Export `ArkEnvError` + +You can now import `ArkEnvError` from `arkenv`: + +```ts +import { ArkEnvError } from "arkenv"; +``` diff --git a/apps/playgrounds/node/index.ts b/apps/playgrounds/node/index.ts index 9ff1723a5..e446bb35e 100644 --- a/apps/playgrounds/node/index.ts +++ b/apps/playgrounds/node/index.ts @@ -1,9 +1,9 @@ -import arkenv from "arkenv"; +import arkenv, { createEnv } from "arkenv"; const env = arkenv({ + NODE_ENV: "'development' | 'production' | 'test' = 'development'", HOST: "string.host", PORT: "number.port", - NODE_ENV: "'development' | 'production' | 'test' = 'development'", }); // Automatically validate and parse process.env diff --git a/apps/www/next.config.ts b/apps/www/next.config.ts index 0b8179a99..baa1b44f0 100644 --- a/apps/www/next.config.ts +++ b/apps/www/next.config.ts @@ -12,7 +12,7 @@ export default withSentryConfig( // For all available options, see: // https://github.com/getsentry/sentry-webpack-plugin#options - org: process.env.SENTRY_ORG, + org: process.env.SENTRY_ORG, project: process.env.SENTRY_PROJECT, // Only print logs for uploading source maps in CI diff --git a/apps/www/package.json b/apps/www/package.json index 4ceb36bfc..3b145d1ac 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -18,6 +18,7 @@ "@radix-ui/react-toast": "^1.2.15", "@sentry/nextjs": "^10.10.0", "@stackblitz/sdk": "^1.11.0", + "arkenv": "workspace:*", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "fumadocs-core": "15.7.10", @@ -31,6 +32,7 @@ "react-dom": "^19.1.1", "rehype-github-alerts": "^4.1.1", "remark-gemoji": "^8.0.0", + "require-in-the-middle": "^7.5.2", "tailwind-merge": "^3.3.1", "tailwindcss-animate": "^1.0.7", "twoslash": "^0.3.4" diff --git a/apps/www/source.config.ts b/apps/www/source.config.ts index d29f4df29..a32eeafa2 100644 --- a/apps/www/source.config.ts +++ b/apps/www/source.config.ts @@ -1,6 +1,7 @@ import { rehypeCodeDefaultOptions, remarkNpm } from "fumadocs-core/mdx-plugins"; import { defineConfig, defineDocs } from "fumadocs-mdx/config"; import { transformerTwoslash } from "fumadocs-twoslash"; +import { createFileSystemTypesCache } from "fumadocs-twoslash/cache-fs"; import { rehypeGithubAlerts } from "rehype-github-alerts"; import remarkGemoji from "remark-gemoji"; @@ -22,7 +23,9 @@ export default defineConfig({ }, transformers: [ ...(rehypeCodeDefaultOptions.transformers ?? []), - transformerTwoslash(), + transformerTwoslash({ + typesCache: createFileSystemTypesCache(), + }), ], }, }, diff --git a/packages/arkenv/src/create-env.ts b/packages/arkenv/src/create-env.ts index 4bc729960..431962967 100644 --- a/packages/arkenv/src/create-env.ts +++ b/packages/arkenv/src/create-env.ts @@ -11,7 +11,7 @@ export type EnvSchema = type.validate; * @param def - The environment variable schema * @param env - The environment variables to validate, defaults to `process.env` * @returns The validated environment variable schema - * @throws An error if the environment variables are invalid. See {@link ArkEnvError} + * @throws An {@link ArkEnvError | error} if the environment variables are invalid. */ export function createEnv>( def: EnvSchema, diff --git a/packages/arkenv/src/index.ts b/packages/arkenv/src/index.ts index 437c32c60..5aae01874 100644 --- a/packages/arkenv/src/index.ts +++ b/packages/arkenv/src/index.ts @@ -2,7 +2,13 @@ export type { EnvSchema } from "./create-env"; import { createEnv } from "./create-env"; +/** + * `arkenv`'s main export, an alias for {@link createEnv} + * + * {@link https://arkenv.js.org | ArkEnv} is a typesafe environment variables parser powered by {@link https://arktype.io | ArkType}, TypeScript's 1:1 validator. + */ const arkenv = createEnv; export default arkenv; export { type } from "./type"; export { createEnv }; +export { ArkEnvError } from "./errors"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 386a70f6e..e61c08fb3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,6 +118,9 @@ importers: '@stackblitz/sdk': specifier: ^1.11.0 version: 1.11.0 + arkenv: + specifier: workspace:* + version: link:../../packages/arkenv class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -157,6 +160,9 @@ importers: remark-gemoji: specifier: ^8.0.0 version: 8.0.0 + require-in-the-middle: + specifier: ^7.5.2 + version: 7.5.2 tailwind-merge: specifier: ^3.3.1 version: 3.3.1 From d7abf71177a8a654519b0917b56b3b0ad0cb09b1 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Sun, 14 Sep 2025 22:40:33 +0500 Subject: [PATCH 04/14] Enhance JSDoc for arkenv and createEnv - Improved the JSDoc comments for `arkenv` and `createEnv` to provide more detailed descriptions, enhancing code documentation clarity. --- .changeset/some-bikes-film.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/some-bikes-film.md diff --git a/.changeset/some-bikes-film.md b/.changeset/some-bikes-film.md new file mode 100644 index 000000000..9e0c9dac2 --- /dev/null +++ b/.changeset/some-bikes-film.md @@ -0,0 +1,8 @@ +--- +"arkenv": patch +--- + +Improve JSDoc + +The JSDoc for `arkenv` and `createEnv` is now more descriptive. + From d5ed1b5076a261438ae3bda662888e26428a7655 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Sun, 14 Sep 2025 23:26:58 +0500 Subject: [PATCH 05/14] Add arkdark dependency and enhance documentation features - Introduced `arkdark` as a new dependency in `pnpm-lock.yaml` for improved functionality. - Updated `index.ts` to simplify the import of `arkenv`. - Enhanced `source.config.ts` to utilize `arkdark` package.json for better documentation integration. - Added CSS styles for Twoslash code blocks to improve user experience. - Removed outdated `type-function.mdx` documentation file to streamline content. --- apps/playgrounds/node/index.ts | 2 +- apps/www/app/styles/base.css | 13 + .../www/content/docs/guides/type-function.mdx | 273 ------------------ apps/www/source.config.ts | 149 +++++++++- pnpm-lock.yaml | 9 + 5 files changed, 171 insertions(+), 275 deletions(-) delete mode 100644 apps/www/content/docs/guides/type-function.mdx diff --git a/apps/playgrounds/node/index.ts b/apps/playgrounds/node/index.ts index e446bb35e..8f3581ffa 100644 --- a/apps/playgrounds/node/index.ts +++ b/apps/playgrounds/node/index.ts @@ -1,4 +1,4 @@ -import arkenv, { createEnv } from "arkenv"; +import arkenv from "arkenv"; const env = arkenv({ NODE_ENV: "'development' | 'production' | 'test' = 'development'", diff --git a/apps/www/app/styles/base.css b/apps/www/app/styles/base.css index 3cc2dbf44..59115e7ee 100644 --- a/apps/www/app/styles/base.css +++ b/apps/www/app/styles/base.css @@ -21,4 +21,17 @@ .fd-steps { padding-left: 2.3rem; } + + /* Twoslash code block max height */ + pre.twoslash { + max-height: 400px; + overflow-y: auto; + overflow-x: auto; + } + + /* Alternative: Target the type source section specifically */ + .twoslash .twoslash-type-source { + max-height: 300px; + overflow-y: auto; + } } diff --git a/apps/www/content/docs/guides/type-function.mdx b/apps/www/content/docs/guides/type-function.mdx deleted file mode 100644 index b90ff2e1f..000000000 --- a/apps/www/content/docs/guides/type-function.mdx +++ /dev/null @@ -1,273 +0,0 @@ ---- -title: "type function" -description: "Learn about ArkEnv's advanced type function for runtime validation with built-in environment-specific types." ---- - -> [!NOTE] -> **For most use cases, you should use the default `arkenv` export (which uses `createEnv` under the hood).** The `type` function is useful when you want to separate schema definition from validation. - -> [!TIP] -> **New to ArkEnv?** Start with the [Quickstart guide](/docs/quickstart) to learn the basics with the default `arkenv` export. This guide is for when you need to separate schema definition from validation. - -ArkEnv exposes a `type` function that extends ArkType's type system with environment-specific validations. This function is useful when you want to define your schema in one place and validate environment variables at a different time or location. - -## Basic Usage - -```ts -import { type } from "arkenv"; - -const env = type({ - NODE_ENV: "string", - HOST: "string.host", - PORT: "number.port", -}); - -// Validate and transform environment variables -const result = env.assert({ - NODE_ENV: "development", - HOST: "localhost", - PORT: "3000", // String input, number output -}); - -console.log(result); -// { NODE_ENV: "development", HOST: "localhost", PORT: 3000 } -``` - -## Separation of Schema Definition and Validation - -The main benefit of the `type` function is that you can define your schema in one place and validate environment variables elsewhere: - -```ts -// config/env-schema.ts -import { type } from "arkenv"; - -export const envSchema = type({ - NODE_ENV: "string", - HOST: "string.host", - PORT: "number.port", - API_KEY: "string?", -}); -``` - -```ts -// config/env.ts -import { envSchema } from "./env-schema"; - -// Validate environment variables using the schema -export const env = envSchema.assert(process.env); -``` - -```ts -// vite.config.ts -import { defineConfig } from "vite"; -import arkenv from "@arkenv/vite-plugin"; -import { envSchema } from "./config/env-schema"; - -export default defineConfig({ - plugins: [arkenv(envSchema)], -}); -``` - -This approach allows you to: -- **Reuse the same schema** across different parts of your application -- **Define schema once** and validate in multiple places -- **Keep configuration modular** and organized - -## Built-in Environment Types - -### `string.host` - -Validates hostnames and IP addresses: - -```ts -const env = type({ - API_HOST: "string.host", - DB_HOST: "string.host", -}); - -// Valid inputs -env.assert({ API_HOST: "localhost" }); -env.assert({ API_HOST: "127.0.0.1" }); -env.assert({ API_HOST: "api.example.com" }); - -// Invalid inputs -env.assert({ API_HOST: "invalid-host" }); // ❌ Throws error -``` - -### `number.port` - -Validates and converts port numbers: - -```ts -const env = type({ - PORT: "number.port", - API_PORT: "number.port", -}); - -// Valid inputs (strings from environment variables) -const result = env.assert({ PORT: "3000" }); -console.log(result.PORT); // 3000 (number) - -// Valid port range: 1-65535 -env.assert({ PORT: "8080" }); // ✅ Valid -env.assert({ PORT: "65535" }); // ✅ Valid - -// Invalid inputs -env.assert({ PORT: "0" }); // ❌ Too low -env.assert({ PORT: "65536" }); // ❌ Too high -env.assert({ PORT: "invalid" }); // ❌ Not a number -``` - -## Advanced Usage - -### Optional Fields - -```ts -const env = type({ - REQUIRED: "string", - OPTIONAL: "string?", - PORT: "number.port?", -}); - -// Works with all fields -env.assert({ - REQUIRED: "value", - OPTIONAL: "optional", - PORT: "3000", -}); - -// Works with only required fields -env.assert({ - REQUIRED: "value", - // OPTIONAL and PORT are omitted -}); -``` - -### Nested Objects - -```ts -const env = type({ - DATABASE: { - HOST: "string.host", - PORT: "number.port", - NAME: "string", - }, - API: { - HOST: "string.host", - PORT: "number.port", - }, -}); - -const result = env.assert({ - DATABASE: { - HOST: "localhost", - PORT: "5432", - NAME: "myapp", - }, - API: { - HOST: "api.example.com", - PORT: "443", - }, -}); -``` - -### Arrays - -```ts -const env = type({ - ALLOWED_ORIGINS: "string[]", - PORTS: "number[]", -}); - -const result = env.assert({ - ALLOWED_ORIGINS: ["localhost", "127.0.0.1"], - PORTS: [3000, 8080, 9000], -}); -``` - -## Error Handling - -The `type` function provides detailed error messages for validation failures: - -```ts -const env = type({ - HOST: "string.host", - PORT: "number.port", -}); - -try { - env.assert({ - HOST: "invalid-host", - PORT: "99999", - }); -} catch (error) { - console.error(error.message); - // HOST must be a valid hostname or IP address (was "invalid-host") - // PORT must be a valid port number (was "99999") -} -``` - -## When to Use `type` vs `arkenv` (default export) - -> [!IMPORTANT] -> **Most users should use the default `arkenv` export for environment variables.** Only use `type` when you need to separate schema definition from validation. - -| Feature | `type` | `arkenv` (default) | -|---------|--------|-------------------| -| **Primary Use Case** | Schema definition separate from validation | Environment variable handling with immediate validation | -| **Input** | Any object (usually environment variables) | `process.env` or custom object | -| **Output** | Validated object | Parsed environment variables | -| **When to Use** | When you want to define schema in one file and validate in another | Environment variables (most common) | -| **Recommended for** | Advanced users, modular architecture | **Most users** | - -```ts -// ✅ RECOMMENDED: Using arkenv for immediate validation -import arkenv from "arkenv"; - -const env = arkenv({ - HOST: "string.host", - PORT: "number.port", -}); - -// ✅ ADVANCED: Using type to separate schema definition from validation -import { type } from "arkenv"; - -// Define schema in one file -const envSchema = type({ - HOST: "string.host", - PORT: "number.port", -}); - -// Validate in another file or at a later time -const validated = envSchema.assert(process.env); -``` - -### Common Use Cases for `type`: - -- **Modular Architecture**: Define schema in a shared config file, validate in different modules -- **Delayed Validation**: Define schema early but validate environment variables later in your application lifecycle -- **Schema Reuse**: Use the same schema definition for different validation scenarios -- **Testing**: Define schema once and use it for testing different environment configurations - -## Integration with Vite - -The `type` function works seamlessly with the Vite plugin: - -```ts -// vite.config.ts -import { defineConfig } from "vite"; -import arkenv from "@arkenv/vite-plugin"; -import { type } from "arkenv"; - -const envSchema = type({ - VITE_API_URL: "string", - VITE_HOST: "string.host", - VITE_PORT: "number.port", -}); - -export default defineConfig({ - plugins: [arkenv(envSchema)], -}); -``` - -This ensures your environment variables are validated at build time with the same type definitions you use for runtime validation. diff --git a/apps/www/source.config.ts b/apps/www/source.config.ts index a32eeafa2..8825667f9 100644 --- a/apps/www/source.config.ts +++ b/apps/www/source.config.ts @@ -1,10 +1,28 @@ +import { createRequire } from "node:module"; import { rehypeCodeDefaultOptions, remarkNpm } from "fumadocs-core/mdx-plugins"; import { defineConfig, defineDocs } from "fumadocs-mdx/config"; -import { transformerTwoslash } from "fumadocs-twoslash"; +import { + type TransformerTwoslashOptions, + transformerTwoslash, +} from "fumadocs-twoslash"; import { createFileSystemTypesCache } from "fumadocs-twoslash/cache-fs"; import { rehypeGithubAlerts } from "rehype-github-alerts"; import remarkGemoji from "remark-gemoji"; +const require = createRequire(import.meta.url); + +/** + * Next.js apparently strips away the "with { type: 'json' }" option, so we need to use the `require` function to import the package.json file. + * + * + * If it weren't for this issue, we'd be able to use: + * + * ```ts + * import arkTypePackageJson from "arkdark/package.json" with { type: "json" }; + * ``` + */ +const arkTypePackageJson = require("arkdark/package.json"); + export const docs = defineDocs({ dir: "content/docs", docs: { @@ -12,6 +30,133 @@ export const docs = defineDocs({ }, }); +/** biome-ignore-start lint/style/useTemplate: Copied from ArkType */ +/** + * Twoslash property prefix {@link https://github.com/arktypeio/arktype/blob/ff7db8b61004f8de82089a22f4cb4ab5938c2a97/ark/docs/lib/shiki.ts#L37 | ripped from ArkType} + */ +const twoslashPropertyPrefix = "(property) "; +/** + * Twoslash options {@link https://github.com/arktypeio/arktype/blob/ff7db8b61004f8de82089a22f4cb4ab5938c2a97/ark/docs/lib/shiki.ts#L38 | ripped from ArkType} + */ +const arktypeTwoslashOptions = { + explicitTrigger: false, + langs: ["ts", "js"], + twoslashOptions: { + compilerOptions: { + // avoid ... in certain longer types on hover + noErrorTruncation: true, + }, + extraFiles: { + "global.d.ts": `import type * as a from "arktype" + +declare global { + const type: typeof a.type + namespace type { + export type cast = { + [a.inferred]?: t + } + + export type errors = a.ArkErrors + + export type validate> = a.validateDefinition< + def, + $, + args + > + + export type instantiate> = type< + a.inferDefinition, + $ + > + + export type infer> = a.inferDefinition< + def, + $, + args + > + + /** @ts-ignore cast variance */ + export interface Any extends a.BaseType {} + } + + type type = a.Type + const scope: typeof a.scope + const match: typeof a.match +}`, + }, + filterNode: (node) => { + switch (node.type) { + case "hover": + if (node.text.endsWith(", {}>")) + // omit default scope param from type display + node.text = node.text.slice(0, -5) + ">"; + if (node.text.startsWith("type")) return true; + + // when `noErrorTruncation` is enabled, TS displays the type + // of an anonymous cyclic type as `any` instead of using + // `...`, so replace it to clarify the type is accurately inferred + node.text = node.text.replaceAll(" any", " ..."); + if (node.text.startsWith("const")) { + // show type with completions populated for known examples + node.text = node.text.replace( + "version?: undefined", + "version?: number | string", + ); + node.text = node.text.replace( + "versions?: undefined", + "versions?: (number | string)[]", + ); + // filter out the type of Type's invocation + // as opposed to the Type itself + return !node.text.includes("(data: unknown)"); + } + if (node.text.startsWith(twoslashPropertyPrefix)) { + const expression = node.text.slice(twoslashPropertyPrefix.length); + if (expression.startsWith("RuntimeErrors.summary") && node.docs) { + // this shows error summary in JSDoc + // re-add spaces stripped out during processing + node.docs = node.docs.replaceAll("•", " •"); + return true; + } + if (expression === `platform: "android" | "ios"`) { + // this helps demonstrate narrowing on discrimination + return true; + } + return false; + } + return false; + case "error": + // adapted from my ErrorLens implementation at + // https://github.com/usernamehw/vscode-error-lens/blob/d1786ddeedee23d70f5f75b16415a6579b554b59/src/utils/extUtils.ts#L127 + for (const transformation of arkTypePackageJson.contributes + .configurationDefaults["errorLens.replace"]) { + const regex = new RegExp(transformation.matcher); + const matchResult = regex.exec(node.text); + if (matchResult) { + node.text = transformation.message; + // Replace groups like $0 and $1 with groups from the match + for ( + let groupIndex = 0; + groupIndex < matchResult.length; + groupIndex++ + ) { + node.text = node.text.replaceAll( + new RegExp(`\\$${groupIndex}`, "gu"), + matchResult[Number(groupIndex)], + ); + } + node.text = `TypeScript: ${node.text}`; + } + } + return true; + default: + return true; + } + }, + }, +} satisfies TransformerTwoslashOptions; +/** biome-ignore-end lint/style/useTemplate: Copied from ArkType */ + export default defineConfig({ mdxOptions: { rehypePlugins: [rehypeGithubAlerts], @@ -24,7 +169,9 @@ export default defineConfig({ transformers: [ ...(rehypeCodeDefaultOptions.transformers ?? []), transformerTwoslash({ + ...arktypeTwoslashOptions, typesCache: createFileSystemTypesCache(), + explicitTrigger: true, }), ], }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e61c08fb3..1d220bc09 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,6 +118,9 @@ importers: '@stackblitz/sdk': specifier: ^1.11.0 version: 1.11.0 + arkdark: + specifier: ^5.4.2 + version: 5.4.2 arkenv: specifier: workspace:* version: link:../../packages/arkenv @@ -2392,6 +2395,10 @@ packages: resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} engines: {node: '>=10'} + arkdark@5.4.2: + resolution: {integrity: sha512-AMk8Jmrgo4X9TJtjwIa7K1zQqHh1OBzSU129IhB5jetFh6mMAhqT0QqyYQshB+4XEvtDeNjtfry+1XiXAoLYNg==} + engines: {vscode: ^1.0.0} + arktype@2.1.22: resolution: {integrity: sha512-xdzl6WcAhrdahvRRnXaNwsipCgHuNoLobRqhiP8RjnfL9Gp947abGlo68GAIyLtxbD+MLzNyH2YR4kEqioMmYQ==} @@ -7014,6 +7021,8 @@ snapshots: dependencies: tslib: 2.8.1 + arkdark@5.4.2: {} + arktype@2.1.22: dependencies: '@ark/schema': 0.49.0 From 8a3b4561ffe0db86b95dbcd6ed608efc7438dee1 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Mon, 15 Sep 2025 00:11:04 +0500 Subject: [PATCH 06/14] Update dependencies and enhance Next.js configuration - Added `@fumadocs/mdx-remote` and `shiki` as new dependencies in `package.json` for improved documentation features. - Updated `pnpm-lock.yaml` to reflect the new versions and peer dependencies. - Enhanced `next.config.ts` to include `ts-morph` in `serverExternalPackages` for better server-side handling. - Modified layout component to include a smooth scroll behavior attribute for improved user experience. --- apps/www/app/layout.tsx | 1 + apps/www/next.config.ts | 101 +++++++++++++------------ apps/www/package.json | 3 + packages/vite-plugin/src/index.test.ts | 26 ++++++- pnpm-lock.yaml | 79 ++++++++++++++++++- 5 files changed, 155 insertions(+), 55 deletions(-) diff --git a/apps/www/app/layout.tsx b/apps/www/app/layout.tsx index ca60a5dc9..d6cc863b4 100644 --- a/apps/www/app/layout.tsx +++ b/apps/www/app/layout.tsx @@ -32,6 +32,7 @@ export default function Layout({ children }: { children: ReactNode }) { lang="en" className={`${inter.className} ${jetbrainsMono.variable}`} suppressHydrationWarning + data-scroll-behavior="smooth" > ; +}; // Run fixture-based tests for (const name of readdirSync(fixturesDir)) { @@ -98,9 +100,25 @@ describe("Plugin Unit Tests", () => { it("should call createEnv during config hook", () => { const pluginInstance = arkenvPlugin({ VITE_TEST: "string" }); - // Mock the config hook - if (pluginInstance.config) { - pluginInstance.config({}, { mode: "test", command: "build" }); + // Mock the config hook with proper context + if (pluginInstance.config && typeof pluginInstance.config === "function") { + const mockContext = { + meta: { + framework: "vite", + version: "1.0.0", + rollupVersion: "4.0.0", + viteVersion: "5.0.0", + }, + error: vi.fn(), + warn: vi.fn(), + info: vi.fn(), + debug: vi.fn(), + } as any; + pluginInstance.config.call( + mockContext, + {}, + { mode: "test", command: "build" }, + ); } expect(mockCreateEnv).toHaveBeenCalledWith( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1d220bc09..ce398cf0a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,6 +100,9 @@ importers: '@ark/util': specifier: ^0.49.0 version: 0.49.0 + '@fumadocs/mdx-remote': + specifier: ^1.4.0 + version: 1.4.0(@types/react@19.1.12)(fumadocs-core@15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1) '@icons-pack/react-simple-icons': specifier: ^13.7.0 version: 13.7.0(react@19.1.1) @@ -135,7 +138,7 @@ importers: version: 15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1) fumadocs-mdx: specifier: 11.9.0 - version: 11.9.0(fumadocs-core@15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1)(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.5)) + version: 11.9.0(@fumadocs/mdx-remote@1.4.0(@types/react@19.1.12)(fumadocs-core@15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1))(fumadocs-core@15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1)(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.5)) fumadocs-twoslash: specifier: ^3.1.7 version: 3.1.7(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(fumadocs-ui@15.7.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(tailwindcss@4.1.13))(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(typescript@5.9.2) @@ -166,6 +169,9 @@ importers: require-in-the-middle: specifier: ^7.5.2 version: 7.5.2 + shiki: + specifier: ^3.12.2 + version: 3.12.2 tailwind-merge: specifier: ^3.3.1 version: 3.3.1 @@ -741,6 +747,16 @@ packages: '@formatjs/intl-localematcher@0.6.1': resolution: {integrity: sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg==} + '@fumadocs/mdx-remote@1.4.0': + resolution: {integrity: sha512-0aECFvjlpCMeDopjXKBndP/7FbzchNOJu0m3qPsKFtZl+/1QvGsrKPYVVnIY5lwvHL7+E9wGhl6MUHrvcqvWCw==} + peerDependencies: + '@types/react': '*' + fumadocs-core: ^14.0.0 || ^15.0.0 + react: 18.x.x || 19.x.x + peerDependenciesMeta: + '@types/react': + optional: true + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -2804,6 +2820,10 @@ packages: resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} engines: {node: '>=12.0.0'} + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -3033,6 +3053,10 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + gray-matter@4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -3148,6 +3172,10 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -3261,6 +3289,10 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -4065,6 +4097,10 @@ packages: scroll-into-view-if-needed@3.1.0: resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} + section-matter@1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -4167,6 +4203,10 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + strip-bom-string@1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -5251,6 +5291,18 @@ snapshots: dependencies: tslib: 2.8.1 + '@fumadocs/mdx-remote@1.4.0(@types/react@19.1.12)(fumadocs-core@15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1)': + dependencies: + '@mdx-js/mdx': 3.1.1 + fumadocs-core: 15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + gray-matter: 4.0.3 + react: 19.1.1 + zod: 4.1.5 + optionalDependencies: + '@types/react': 19.1.12 + transitivePeerDependencies: + - supports-color + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -7444,6 +7496,10 @@ snapshots: expect-type@1.2.2: {} + extend-shallow@2.0.1: + dependencies: + is-extendable: 0.1.1 + extend@3.0.2: {} extendable-error@0.1.7: {} @@ -7559,7 +7615,7 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-mdx@11.9.0(fumadocs-core@15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1)(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.5)): + fumadocs-mdx@11.9.0(@fumadocs/mdx-remote@1.4.0(@types/react@19.1.12)(fumadocs-core@15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1))(fumadocs-core@15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1)(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.5)): dependencies: '@mdx-js/mdx': 3.1.1 '@standard-schema/spec': 1.0.0 @@ -7578,6 +7634,7 @@ snapshots: unist-util-visit: 5.0.0 zod: 4.1.5 optionalDependencies: + '@fumadocs/mdx-remote': 1.4.0(@types/react@19.1.12)(fumadocs-core@15.7.10(@types/react@19.1.12)(next@15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1) next: 15.5.2(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) react: 19.1.1 vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.5) @@ -7706,6 +7763,13 @@ snapshots: graphemer@1.4.0: {} + gray-matter@4.0.3: + dependencies: + js-yaml: 3.14.1 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + has-flag@4.0.0: {} hasown@2.0.2: @@ -7890,6 +7954,8 @@ snapshots: is-decimal@2.0.1: {} + is-extendable@0.1.1: {} + is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} @@ -8000,6 +8066,8 @@ snapshots: dependencies: json-buffer: 3.0.1 + kind-of@6.0.3: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -9085,6 +9153,11 @@ snapshots: dependencies: compute-scroll-into-view: 3.1.1 + section-matter@1.0.0: + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + semver@6.3.1: {} semver@7.7.2: {} @@ -9210,6 +9283,8 @@ snapshots: dependencies: ansi-regex: 6.2.0 + strip-bom-string@1.0.0: {} + strip-bom@3.0.0: {} strip-json-comments@3.1.1: {} From 19699e38089b3dde7f292d5d14e4139d18e3e671 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Mon, 15 Sep 2025 00:30:11 +0500 Subject: [PATCH 07/14] Update code block syntax for consistency and improve documentation clarity - Changed code block language from `typescript` to `ts` in multiple documentation files for uniformity. - Added a newline at the end of the `examples.mdx` file to adhere to formatting standards. --- apps/www/content/docs/examples.mdx | 2 +- apps/www/content/docs/integrations/import-guide.mdx | 2 +- apps/www/content/docs/quickstart.mdx | 2 +- packages/arkenv/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/www/content/docs/examples.mdx b/apps/www/content/docs/examples.mdx index 2f2884bfd..f1f3b15ce 100644 --- a/apps/www/content/docs/examples.mdx +++ b/apps/www/content/docs/examples.mdx @@ -10,4 +10,4 @@ description: Explore our collection of examples to get started with ArkEnv - \ No newline at end of file + diff --git a/apps/www/content/docs/integrations/import-guide.mdx b/apps/www/content/docs/integrations/import-guide.mdx index c149f9104..6ae4a71ba 100644 --- a/apps/www/content/docs/integrations/import-guide.mdx +++ b/apps/www/content/docs/integrations/import-guide.mdx @@ -4,7 +4,7 @@ title: How to import ArkEnv to enable syntax highlighting To integrate ArkEnv, use the **default import** and name it `arkenv`: -```typescript +```ts twoslash import arkenv from 'arkenv'; const env = arkenv({ diff --git a/apps/www/content/docs/quickstart.mdx b/apps/www/content/docs/quickstart.mdx index dad631ace..d32f0ea66 100644 --- a/apps/www/content/docs/quickstart.mdx +++ b/apps/www/content/docs/quickstart.mdx @@ -34,7 +34,7 @@ description: Let's get you started with a few simple steps Add a schema to make your environment variables **validated** and **typesafe**: - ```typescript title="config/env.ts" twoslash + ```ts title="config/env.ts" twoslash import arkenv from 'arkenv'; export const env = arkenv({ diff --git a/packages/arkenv/README.md b/packages/arkenv/README.md index c229e1e38..b7881e62e 100644 --- a/packages/arkenv/README.md +++ b/packages/arkenv/README.md @@ -29,7 +29,7 @@ ArkEnv is an environment variable parser powered by [ArkType](https://arktype.io/), TypeScript's 1:1 validator. ArkEnv lets you use familiar TypeScript-like syntax to create a ready to use, typesafe environment variable object: -```ts +```ts twoslash import arkenv from 'arkenv'; const env = arkenv({ From 8dc99739e04761a4ecb157d8e93f8750534a4e6f Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Mon, 15 Sep 2025 01:47:32 +0500 Subject: [PATCH 08/14] Enhance documentation clarity and consistency - Updated code block titles and formatting in `quickstart.mdx` and `environment-configuration.mdx` for improved readability. - Standardized section headings to follow consistent capitalization rules across the documentation. - Added example code for environment variable validation in `quickstart.mdx` to illustrate usage of `arkenv` more effectively. --- .../docs/guides/environment-configuration.mdx | 68 ++++++++----------- apps/www/content/docs/quickstart.mdx | 13 +++- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/apps/www/content/docs/guides/environment-configuration.mdx b/apps/www/content/docs/guides/environment-configuration.mdx index 997e30af6..c7fd438f1 100644 --- a/apps/www/content/docs/guides/environment-configuration.mdx +++ b/apps/www/content/docs/guides/environment-configuration.mdx @@ -3,9 +3,9 @@ title: Loading environment variables description: Learn how to manage environment variables across different environments and deployment scenarios --- -## Local Development +## Local development -### Using `.env` Files +### Using `.env` files The most common way to manage environment variables during development is using `.env` files: @@ -17,9 +17,9 @@ API_KEY=your-secret-key LOG_LEVEL=debug ``` -### Best Practices for `.env` Files +### Best practices for `.env` files -1. **Document Required Variables** +1. **Document required variables** Create a `.env.example` file to document required variables: ```dotenv title=".env.example" DATABASE_HOST=localhost @@ -29,7 +29,7 @@ LOG_LEVEL=debug LOG_LEVEL=info ``` -2. **Gitignore Configuration** +2. **Gitignore configuration** Add these patterns to your `.gitignore`: ```dotenv title=".gitignore" .env @@ -37,7 +37,7 @@ LOG_LEVEL=debug !.env.example ``` -3. **Environment-Specific Files** +3. **Environment-specific files** Use different files for different environments: - `.env.development` - Development settings - `.env.test` - Test environment settings @@ -56,7 +56,7 @@ import * as dotenv from 'dotenv'; dotenv.config(); ``` -### Framework-Specific Solutions +### Framework-specific solutions Many frameworks have built-in support for environment variables: @@ -92,7 +92,7 @@ import { ConfigModule } from '@nestjs/config'; }) ``` -### Runtime Arguments +### Runtime arguments You can also supply variables when running your application: @@ -100,9 +100,9 @@ You can also supply variables when running your application: DATABASE_HOST=localhost DATABASE_PORT=5432 npm start ``` -## Production Deployment +## Production deployment -### Cloud Platforms +### Cloud platforms #### AWS - Use AWS Systems Manager Parameter Store for non-sensitive values @@ -117,7 +117,7 @@ DATABASE_HOST=localhost DATABASE_PORT=5432 npm start - Use Azure Key Vault for sensitive values - Configure App Settings in Azure App Service -### Container Environments +### Container environments #### Docker @@ -148,13 +148,13 @@ spec: key: database-host ``` -### Traditional Hosting +### Traditional hosting - Set environment variables through the hosting platform's dashboard - Use deployment scripts to configure environment variables - Consider using configuration management tools -## Security Best Practices +## Security best practices 1. **Never commit sensitive values** - Keep `.env` files out of version control @@ -164,7 +164,7 @@ spec: - Don't share sensitive credentials between environments - Use environment-specific configurations -3. **Access Control** +3. **Access control** - Limit access to production environment variables - Use role-based access control for secrets management @@ -172,11 +172,11 @@ spec: - Encrypt sensitive values at rest - Use secure channels for transmitting secrets -## Validation and Typesafety +## Validation and typesafety ArkEnv helps ensure your environment variables are valid: -```typescript title="src/config/env.ts" +```typescript title="src/config/env.ts" twoslash import arkenv from 'arkenv'; export const env = arkenv({ @@ -188,27 +188,17 @@ export const env = arkenv({ LOG_LEVEL: "'debug' | 'info' | 'warn' | 'error' = 'info'", // Optional variables - "FEATURE_FLAGS?": 'string[]', - - // Custom validation - API_URL: (value: string) => { - try { - new URL(value); - return true; - } catch { - return false; - } - } + "FEATURE_FLAGS?": 'string[]' }); ``` -## Common Patterns +## Common patterns -### Configuration Factory +### Configuration factory Create a configuration factory to handle different environments: -```typescript title="src/config/index.ts" +```typescript title="src/config/index.ts" twoslash import arkenv from 'arkenv'; const createConfig = () => { @@ -230,35 +220,35 @@ const createConfig = () => { export const config = createConfig(); ``` -### Feature Flags +### Feature flags Use environment variables for feature flags: -```typescript title="src/config/features.ts" +```typescript title="src/config/features.ts" twoslash import arkenv from 'arkenv'; export const env = arkenv({ - "ENABLE_BETA_FEATURES?": 'boolean = false', - "MAINTENANCE_MODE?": 'boolean = false', - "ALLOWED_ORIGINS?": 'string[] = []' + "ENABLE_BETA_FEATURES": 'boolean = false', + "MAINTENANCE_MODE": 'boolean = false', + "ALLOWED_ORIGINS": ['string[]', '=', []] }); ``` ## Troubleshooting -### Common Issues +### Common issues -1. **Missing Variables** +1. **Missing variables** - Check if `.env` file exists - Verify variable names match exactly - Ensure variables are loaded before use -2. **Type Errors** +2. **Type errors** - Verify variable types match schema - Check for typos in variable names - Ensure all required variables are provided -3. **Loading Order** +3. **Loading order** - Load environment variables before importing config - Consider using a bootstrap file - Check framework-specific loading behavior diff --git a/apps/www/content/docs/quickstart.mdx b/apps/www/content/docs/quickstart.mdx index d32f0ea66..2c8084e76 100644 --- a/apps/www/content/docs/quickstart.mdx +++ b/apps/www/content/docs/quickstart.mdx @@ -98,7 +98,18 @@ description: Let's get you started with a few simple steps Import and use your **validated** and **typed** environment variables. For example, you might have a file like `database.ts`: - ```typescript title="database.ts" + ```typescript title="database.ts" twoslash + // @filename: config/env.ts + import arkenv from 'arkenv'; + export const env = arkenv({ + DATABASE_HOST: "string.host", + DATABASE_PORT: "number.port", + NODE_ENV: "'development' | 'production' | 'test'", + LOG_LEVEL: "'debug' | 'info' | 'warn' | 'error' = 'info'", + "API_KEY?": 'string' + }); + // @filename: database.ts + // ---cut--- import { env } from './config/env'; // TypeScript knows the ✨exact✨ types! From fa707c8c269709ed6a60135fa539a50217a88a10 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Mon, 15 Sep 2025 01:50:36 +0500 Subject: [PATCH 09/14] Refactor ALLOWED_ORIGINS configuration in environment-configuration.mdx - Changed the type definition of "ALLOWED_ORIGINS" from an array to a string array for clarity and correctness in environment variable configuration. --- apps/www/content/docs/guides/environment-configuration.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/www/content/docs/guides/environment-configuration.mdx b/apps/www/content/docs/guides/environment-configuration.mdx index c7fd438f1..b2065fa5d 100644 --- a/apps/www/content/docs/guides/environment-configuration.mdx +++ b/apps/www/content/docs/guides/environment-configuration.mdx @@ -230,7 +230,7 @@ import arkenv from 'arkenv'; export const env = arkenv({ "ENABLE_BETA_FEATURES": 'boolean = false', "MAINTENANCE_MODE": 'boolean = false', - "ALLOWED_ORIGINS": ['string[]', '=', []] + "ALLOWED_ORIGINS": 'string[]' }); ``` From 52ac9cc6d67a31c3325eda322c55674718db2f65 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Mon, 15 Sep 2025 02:09:43 +0500 Subject: [PATCH 10/14] Update middleware matcher to exclude monitoring paths - Modified the matcher configuration in `middleware.ts` to prevent routing for paths that include "monitoring", enhancing request handling. --- apps/www/middleware.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/www/middleware.ts b/apps/www/middleware.ts index a6809c629..63ec4e893 100644 --- a/apps/www/middleware.ts +++ b/apps/www/middleware.ts @@ -15,5 +15,5 @@ export function middleware(_request: NextRequest) { } export const config = { - matcher: "/:path*", + matcher: "/((?!monitoring).*)", }; From fcafe1cc52bd1d3eb5a13074be681a5d4ede7540 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Mon, 15 Sep 2025 02:19:24 +0500 Subject: [PATCH 11/14] Refactor Twoslash CSS styles for improved usability - Removed outdated styles for `pre.twoslash` and replaced them with a new class `.fd-twoslash-popover` to set a maximum height of 160px, enhancing the display of Twoslash code blocks. --- apps/www/app/styles/base.css | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/www/app/styles/base.css b/apps/www/app/styles/base.css index 59115e7ee..230457da4 100644 --- a/apps/www/app/styles/base.css +++ b/apps/www/app/styles/base.css @@ -23,15 +23,7 @@ } /* Twoslash code block max height */ - pre.twoslash { - max-height: 400px; - overflow-y: auto; - overflow-x: auto; - } - - /* Alternative: Target the type source section specifically */ - .twoslash .twoslash-type-source { - max-height: 300px; - overflow-y: auto; + .fd-twoslash-popover { + max-height: 160px; } } From c5ede3d0d6a11c0417767f96808c4b0a6ec5c3bc Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Mon, 15 Sep 2025 02:25:54 +0500 Subject: [PATCH 12/14] Update Twoslash popover CSS to enforce maximum height - Added !important to the max-height property of the .fd-twoslash-popover class in base.css to ensure consistent display of Twoslash code blocks across different contexts. --- apps/www/app/styles/base.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/www/app/styles/base.css b/apps/www/app/styles/base.css index 230457da4..6188b5740 100644 --- a/apps/www/app/styles/base.css +++ b/apps/www/app/styles/base.css @@ -24,6 +24,6 @@ /* Twoslash code block max height */ .fd-twoslash-popover { - max-height: 160px; + max-height: 160px !important; } } From 9c913360c44ca9953a5efc44d7d7215dd45c83e8 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Mon, 15 Sep 2025 02:36:02 +0500 Subject: [PATCH 13/14] Refactor Twoslash CSS class for improved structure - Changed the class name from `.fd-twoslash-popover` to `.twoslash .fd-scroll-component` in base.css to enhance the organization of Twoslash styles and maintain consistent maximum height settings for code blocks. --- apps/www/app/styles/base.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/www/app/styles/base.css b/apps/www/app/styles/base.css index 6188b5740..9e2b3f4af 100644 --- a/apps/www/app/styles/base.css +++ b/apps/www/app/styles/base.css @@ -23,7 +23,7 @@ } /* Twoslash code block max height */ - .fd-twoslash-popover { + .twoslash .fd-scroll-component { max-height: 160px !important; } } From 2d7ea5a788ade62174f4668d3121126d66a78bea Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Mon, 15 Sep 2025 02:43:01 +0500 Subject: [PATCH 14/14] Update Twoslash CSS class for consistency in styling - Renamed the class from `.fd-scroll-component` to `.fd-scroll-container` in base.css to align with naming conventions and improve clarity in the Twoslash styling structure. --- apps/www/app/styles/base.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/www/app/styles/base.css b/apps/www/app/styles/base.css index 9e2b3f4af..7ce6fba92 100644 --- a/apps/www/app/styles/base.css +++ b/apps/www/app/styles/base.css @@ -23,7 +23,7 @@ } /* Twoslash code block max height */ - .twoslash .fd-scroll-component { + .twoslash .fd-scroll-container { max-height: 160px !important; } }