doccupine 0.0.71 → 0.0.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ class MDXToNextJSGenerator {
26
26
  configWatcher = null;
27
27
  fontWatcher = null;
28
28
  publicWatcher = null;
29
+ rootDirWatcher = null;
29
30
  analyticsWatcher = null;
30
31
  configFiles = [
31
32
  "theme.json",
@@ -552,27 +553,53 @@ class MDXToNextJSGenerator {
552
553
  });
553
554
  const publicDir = path.join(this.rootDir, "public");
554
555
  if (await fs.pathExists(publicDir)) {
555
- this.publicWatcher = chokidar.watch(publicDir, {
556
- persistent: true,
557
- ignoreInitial: true,
558
- });
559
- this.publicWatcher
560
- .on("add", (filePath) => {
561
- console.log(chalk.cyan(`📁 Public file added: ${path.relative(publicDir, filePath)}`));
562
- this.handlePublicFileChange(filePath);
563
- })
564
- .on("change", (filePath) => {
565
- console.log(chalk.cyan(`📁 Public file changed: ${path.relative(publicDir, filePath)}`));
566
- this.handlePublicFileChange(filePath);
567
- })
568
- .on("unlink", (filePath) => {
569
- console.log(chalk.red(`🗑️ Public file deleted: ${path.relative(publicDir, filePath)}`));
570
- this.handlePublicFileDelete(filePath);
571
- })
572
- .on("error", (error) => {
573
- console.error(chalk.red("❌ Public watcher error:"), error);
574
- });
556
+ this.setupPublicWatcher();
575
557
  }
558
+ // Watch rootDir for public directory creation
559
+ this.rootDirWatcher = chokidar.watch(this.rootDir, {
560
+ persistent: true,
561
+ ignoreInitial: true,
562
+ depth: 0,
563
+ });
564
+ this.rootDirWatcher
565
+ .on("addDir", async (dirPath) => {
566
+ if (path.basename(dirPath) === "public" &&
567
+ path.dirname(dirPath) === this.rootDir &&
568
+ !this.publicWatcher) {
569
+ console.log(chalk.cyan("📁 Public directory created"));
570
+ await this.copyPublicFiles();
571
+ this.setupPublicWatcher();
572
+ }
573
+ })
574
+ .on("error", (error) => {
575
+ console.error(chalk.red("❌ Root dir watcher error:"), error);
576
+ });
577
+ }
578
+ setupPublicWatcher() {
579
+ if (this.publicWatcher) {
580
+ return;
581
+ }
582
+ const publicDir = path.join(this.rootDir, "public");
583
+ this.publicWatcher = chokidar.watch(publicDir, {
584
+ persistent: true,
585
+ ignoreInitial: true,
586
+ });
587
+ this.publicWatcher
588
+ .on("add", (filePath) => {
589
+ console.log(chalk.cyan(`📁 Public file added: ${path.relative(publicDir, filePath)}`));
590
+ this.handlePublicFileChange(filePath);
591
+ })
592
+ .on("change", (filePath) => {
593
+ console.log(chalk.cyan(`📁 Public file changed: ${path.relative(publicDir, filePath)}`));
594
+ this.handlePublicFileChange(filePath);
595
+ })
596
+ .on("unlink", (filePath) => {
597
+ console.log(chalk.red(`🗑️ Public file deleted: ${path.relative(publicDir, filePath)}`));
598
+ this.handlePublicFileDelete(filePath);
599
+ })
600
+ .on("error", (error) => {
601
+ console.error(chalk.red("❌ Public watcher error:"), error);
602
+ });
576
603
  }
577
604
  async parseMDXFile(file) {
578
605
  const fullPath = path.join(this.watchDir, file);
@@ -839,6 +866,9 @@ export default function Page() {
839
866
  await this.publicWatcher.close();
840
867
  console.log(chalk.yellow("👋 Stopped watching for public directory changes"));
841
868
  }
869
+ if (this.rootDirWatcher) {
870
+ await this.rootDirWatcher.close();
871
+ }
842
872
  }
843
873
  }
844
874
  program
@@ -1 +1 @@
1
- export declare const buttonTemplate = "\"use client\";\nimport Link from \"next/link\";\nimport styled from \"styled-components\";\nimport {\n theme as localTheme,\n ButtonProps,\n buttonStyles,\n} from \"cherry-styled-components\";\nimport { Icon } from \"@/components/layout/Icon\";\n\ninterface LinkButtonProps extends ButtonProps {\n href?: string;\n target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\";\n variant?: \"primary\" | \"secondary\" | \"tertiary\";\n size?: \"default\" | \"big\";\n outline?: boolean;\n fullWidth?: boolean;\n icon?: string;\n iconPosition?: \"left\" | \"right\";\n theme?: typeof localTheme;\n}\n\nconst StyledLinkButton = styled(Link)<LinkButtonProps>`\n ${({ theme, $variant, $size, $outline, $fullWidth, disabled }) =>\n buttonStyles(theme, $variant, $size, $outline, $fullWidth, disabled)}\n\n & svg.lucide {\n margin: auto 0;\n min-width: min-content;\n color: inherit;\n }\n`;\n\nconst ButtonBase = styled.button<ButtonProps>`\n ${({ theme, $variant, $size, $outline, $fullWidth, disabled }) =>\n buttonStyles(theme, $variant, $size, $outline, $fullWidth, disabled)}\n\n & svg.lucide {\n margin: auto 0;\n min-width: min-content;\n color: inherit;\n }\n`;\n\nfunction Button({\n variant = \"primary\",\n size,\n outline,\n fullWidth,\n icon,\n iconPosition = \"left\",\n theme: _theme = localTheme,\n href,\n ...props\n}: LinkButtonProps) {\n return href ? (\n <div>\n <StyledLinkButton\n {...props}\n href={href}\n $variant={variant}\n $size={size}\n $outline={outline}\n $fullWidth={fullWidth}\n >\n {iconPosition === \"left\" && icon && <Icon name={icon} size={16} />}\n {props.children}\n {iconPosition === \"right\" && icon && <Icon name={icon} size={16} />}\n </StyledLinkButton>\n </div>\n ) : (\n <div>\n <ButtonBase\n {...props}\n $variant={variant}\n $size={size}\n $outline={outline}\n $fullWidth={fullWidth}\n >\n {iconPosition === \"left\" && icon && <Icon name={icon} size={16} />}\n {props.children}\n {iconPosition === \"right\" && icon && <Icon name={icon} size={16} />}\n </ButtonBase>\n </div>\n );\n}\n\nexport { Button };\n";
1
+ export declare const buttonTemplate = "\"use client\";\nimport Link from \"next/link\";\nimport styled from \"styled-components\";\nimport {\n theme as localTheme,\n ButtonProps,\n buttonStyles,\n} from \"cherry-styled-components\";\nimport { Icon } from \"@/components/layout/Icon\";\n\ninterface LinkButtonProps extends ButtonProps {\n href?: string;\n target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\";\n variant?: \"primary\" | \"secondary\" | \"tertiary\";\n size?: \"default\" | \"big\";\n outline?: boolean;\n fullWidth?: boolean;\n icon?: string;\n iconPosition?: \"left\" | \"right\";\n theme?: typeof localTheme;\n}\n\nconst StyledLinkButton = styled(Link)<LinkButtonProps>`\n ${({ theme, $variant, $size, $outline, $fullWidth, disabled }) =>\n buttonStyles(theme, $variant, $size, $outline, $fullWidth, disabled)}\n\n & p {\n color: inherit;\n }\n\n & svg.lucide {\n margin: auto 0;\n min-width: min-content;\n color: inherit;\n }\n`;\n\nconst ButtonBase = styled.button<ButtonProps>`\n ${({ theme, $variant, $size, $outline, $fullWidth, disabled }) =>\n buttonStyles(theme, $variant, $size, $outline, $fullWidth, disabled)}\n\n & p {\n color: inherit;\n }\n\n & svg.lucide {\n margin: auto 0;\n min-width: min-content;\n color: inherit;\n }\n`;\n\nfunction Button({\n variant = \"primary\",\n size,\n outline,\n fullWidth,\n icon,\n iconPosition = \"left\",\n theme: _theme = localTheme,\n href,\n ...props\n}: LinkButtonProps) {\n return href ? (\n <div>\n <StyledLinkButton\n {...props}\n href={href}\n $variant={variant}\n $size={size}\n $outline={outline}\n $fullWidth={fullWidth}\n >\n {iconPosition === \"left\" && icon && <Icon name={icon} size={16} />}\n {props.children}\n {iconPosition === \"right\" && icon && <Icon name={icon} size={16} />}\n </StyledLinkButton>\n </div>\n ) : (\n <div>\n <ButtonBase\n {...props}\n $variant={variant}\n $size={size}\n $outline={outline}\n $fullWidth={fullWidth}\n >\n {iconPosition === \"left\" && icon && <Icon name={icon} size={16} />}\n {props.children}\n {iconPosition === \"right\" && icon && <Icon name={icon} size={16} />}\n </ButtonBase>\n </div>\n );\n}\n\nexport { Button };\n";
@@ -24,6 +24,10 @@ const StyledLinkButton = styled(Link)<LinkButtonProps>\`
24
24
  \${({ theme, $variant, $size, $outline, $fullWidth, disabled }) =>
25
25
  buttonStyles(theme, $variant, $size, $outline, $fullWidth, disabled)}
26
26
 
27
+ & p {
28
+ color: inherit;
29
+ }
30
+
27
31
  & svg.lucide {
28
32
  margin: auto 0;
29
33
  min-width: min-content;
@@ -35,6 +39,10 @@ const ButtonBase = styled.button<ButtonProps>\`
35
39
  \${({ theme, $variant, $size, $outline, $fullWidth, disabled }) =>
36
40
  buttonStyles(theme, $variant, $size, $outline, $fullWidth, disabled)}
37
41
 
42
+ & p {
43
+ color: inherit;
44
+ }
45
+
38
46
  & svg.lucide {
39
47
  margin: auto 0;
40
48
  min-width: min-content;
@@ -1 +1 @@
1
- export declare const globalStylesTemplate = "\"use client\";\nimport { createGlobalStyle } from \"styled-components\";\n\nconst GlobalStyles = createGlobalStyle`\nhtml,\nbody {\n margin: 0;\n padding: 0;\n min-height: 100%;\n background-color: ${({ theme }) => theme.colors.light};\n scroll-padding-top: 80px;\n}\n\nhtml:has(:target) {\n scroll-behavior: smooth;\n}\n\nbody {\n font-family: \"Inter\", sans-serif;\n -moz-osx-font-smoothing: grayscale;\n -webkit-text-size-adjust: 100%;\n -webkit-font-smoothing: antialiased;\n}\n\n:root {\n interpolate-size: allow-keywords;\n}\n\n* {\n box-sizing: border-box;\n min-width: 0;\n}\n\nhr {\n border: none;\n border-bottom: solid 1px ${({ theme }) => theme.colors.grayLight};\n margin: 10px 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace;\n}\n\npre,\ncode,\nkbd,\nsamp,\nblockquote,\np,\na,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nul li,\nol li {\n margin: 0;\n padding: 0;\n color: ${({ theme }) => theme.colors.dark};\n}\n\na {\n color: ${({ theme }) => (theme.isDark ? theme.colors.dark : theme.colors.primary)};\n}\n\nol,\nul {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\nfigure {\n margin: 0;\n}\n\nfieldset {\n appearance: none;\n border: none;\n}\n\nbutton,\ninput,\na,\nimg,\nsvg,\nsvg * {\n transition: all 0.3s ease;\n}\n\nstrong,\nb {\n font-weight: 700;\n}\n\n.full-width {\n width: 100%;\n}`;\n\nexport { GlobalStyles };\n";
1
+ export declare const globalStylesTemplate = "\"use client\";\nimport { createGlobalStyle } from \"styled-components\";\n\nconst GlobalStyles = createGlobalStyle`\nhtml,\nbody {\n margin: 0;\n padding: 0;\n min-height: 100%;\n background-color: ${({ theme }) => theme.colors.light};\n scroll-padding-top: 80px;\n}\n\nhtml:has(:target) {\n scroll-behavior: smooth;\n}\n\nbody {\n font-family: \"Inter\", sans-serif;\n -moz-osx-font-smoothing: grayscale;\n -webkit-text-size-adjust: 100%;\n -webkit-font-smoothing: antialiased;\n}\n\n:root {\n interpolate-size: allow-keywords;\n}\n\n* {\n box-sizing: border-box;\n min-width: 0;\n}\n\nhr {\n border: none;\n border-bottom: solid 1px ${({ theme }) => theme.colors.grayLight};\n margin: 10px 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace;\n}\n\npre,\ncode,\nkbd,\nsamp,\nblockquote,\np,\na,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nul li,\nol li {\n margin: 0;\n padding: 0;\n color: ${({ theme }) => theme.colors.dark};\n}\n\na {\n color: ${({ theme }) => (theme.isDark ? theme.colors.dark : theme.colors.primary)};\n}\n\nol,\nul {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\nfigure {\n margin: 0;\n}\n\nfieldset {\n appearance: none;\n border: none;\n}\n\nbutton,\ninput,\na,\nimg,\nsvg,\nsvg * {\n transition: all 0.3s ease;\n}\n\nstrong,\nb {\n font-weight: 700;\n}\n\n.full-width {\n width: 100%;\n}\n\n.light-only {\n ${({ theme }) => theme.isDark && \"display: none !important;\"}\n}\n\n.dark-only {\n ${({ theme }) => !theme.isDark && \"display: none !important;\"}\n}`;\n\nexport { GlobalStyles };\n";
@@ -100,6 +100,14 @@ b {
100
100
 
101
101
  .full-width {
102
102
  width: 100%;
103
+ }
104
+
105
+ .light-only {
106
+ \${({ theme }) => theme.isDark && "display: none !important;"}
107
+ }
108
+
109
+ .dark-only {
110
+ \${({ theme }) => !theme.isDark && "display: none !important;"}
103
111
  }\`;
104
112
 
105
113
  export { GlobalStyles };
@@ -1 +1 @@
1
- export declare const imageAndEmbedsMdxTemplate = "---\ntitle: \"Images and embeds\"\ndescription: \"Enrich your documentation with visuals, videos, and interactive embeds.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 8\n---\n# Images and embeds\nEnrich your documentation with visuals, videos, and interactive embeds.\n\nDisplay images, embed video content, or add interactive frames via iframes to supplement your docs.\n\n![Demo Image](https://docs.doccupine.com/demo.png)\n\n## Images\nImages enhance documentation with context, illustration, or decorative visual cues.\n\n### Basic Image Syntax\nInclude an image in Markdown using the syntax below:\n\n```md\n![Alt text](https://docs.doccupine.com/demo.png)\n```\n\n<Callout type=\"note\">\n Use clear, descriptive alt text for accessibility and better SEO. Alt text should describe the image\u2019s appearance or content.\n</Callout>\n\n### HTML image embeds\nEmbed images in your Markdown content using HTML syntax.\n\n```md\n<img src=\"https://docs.doccupine.com/demo.png\" alt=\"Alt text\">\n```\n\n## Videos\nVideos add a dynamic element to your documentation, engaging your audience and providing a more immersive experience.\n\n### YouTube Embed\nTo embed a YouTube video, use the following syntax:\n\n```html\n<iframe\n className=\"aspect-video\"\n src=\"https://www.youtube.com/embed/ResP_eVPYQo\"\n title=\"YouTube video player\"\n frameBorder=\"0\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n></iframe>\n```\n\n<iframe\n className=\"aspect-video\"\n src=\"https://www.youtube.com/embed/ResP_eVPYQo\"\n title=\"YouTube video player\"\n frameBorder=\"0\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n></iframe>\n\n### Self-hosted videos\nServe up your own video content using the `<video>` tag:\n\n```html\n<video\n controls\n className=\"aspect-video\"\n src=\"https://samplelib.com/lib/preview/mp4/sample-20s.mp4\"\n></video>\n```\n\n<video\n controls\n className=\"aspect-video\"\n src=\"https://samplelib.com/lib/preview/mp4/sample-20s.mp4\"\n></video>\n\n\n#### Autoplay and Looping\nFor demonstration videos that loop or start automatically, add attributes as shown:\n\n```html\n<video\n controls\n className=\"aspect-video\"\n src=\"https://samplelib.com/lib/preview/mp4/sample-20s.mp4\"\n autoPlay\n muted\n loop\n playsInline\n></video>\n```\n";
1
+ export declare const imageAndEmbedsMdxTemplate = "---\ntitle: \"Images and embeds\"\ndescription: \"Enrich your documentation with visuals, videos, and interactive embeds.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 8\n---\n# Images and embeds\nEnrich your documentation with visuals, videos, and interactive embeds.\n\nDisplay images, embed video content, or add interactive frames via iframes to supplement your docs.\n\n![Demo Image](https://docs.doccupine.com/demo.png)\n\n## Images\nImages enhance documentation with context, illustration, or decorative visual cues.\n\n### Basic Image Syntax\nInclude an image in Markdown using the syntax below:\n\n```md\n![Alt text](https://docs.doccupine.com/demo.png)\n```\n\n<Callout type=\"note\">\n Use clear, descriptive alt text for accessibility and better SEO. Alt text should describe the image\u2019s appearance or content.\n</Callout>\n\n### HTML image embeds\nEmbed images in your Markdown content using HTML syntax.\n\n```md\n<img src=\"https://docs.doccupine.com/demo.png\" alt=\"Alt text\">\n```\n\n### Theme-aware images\nShow different images depending on whether the user is in light or dark mode. Add the `light-only` or `dark-only` className to display an image exclusively in that theme.\n\n```md\n<img className=\"light-only\" src=\"/images/diagram-light.png\" alt=\"Diagram\">\n<img className=\"dark-only\" src=\"/images/diagram-dark.png\" alt=\"Diagram\">\n```\n\n<img className=\"light-only\" src=\"https://docs.doccupine.com/demo.png\" alt=\"This image is only visible in light mode\">\n<img className=\"dark-only\" src=\"https://docs.doccupine.com/demo.png\" alt=\"This image is only visible in dark mode\" style={{ filter: \"invert(1)\" }}>\n\n<Callout type=\"note\">\n The `light-only` and `dark-only` classes work on any element, not just images. You can use them on videos, iframes, or wrapper divs too.\n</Callout>\n\n## Videos\nVideos add a dynamic element to your documentation, engaging your audience and providing a more immersive experience.\n\n### YouTube Embed\nTo embed a YouTube video, use the following syntax:\n\n```html\n<iframe\n className=\"aspect-video\"\n src=\"https://www.youtube.com/embed/ResP_eVPYQo\"\n title=\"YouTube video player\"\n frameBorder=\"0\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n></iframe>\n```\n\n<iframe\n className=\"aspect-video\"\n src=\"https://www.youtube.com/embed/ResP_eVPYQo\"\n title=\"YouTube video player\"\n frameBorder=\"0\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n></iframe>\n\n### Self-hosted videos\nServe up your own video content using the `<video>` tag:\n\n```html\n<video\n controls\n className=\"aspect-video\"\n src=\"https://samplelib.com/lib/preview/mp4/sample-20s.mp4\"\n></video>\n```\n\n<video\n controls\n className=\"aspect-video\"\n src=\"https://samplelib.com/lib/preview/mp4/sample-20s.mp4\"\n></video>\n\n\n#### Autoplay and Looping\nFor demonstration videos that loop or start automatically, add attributes as shown:\n\n```html\n<video\n controls\n className=\"aspect-video\"\n src=\"https://samplelib.com/lib/preview/mp4/sample-20s.mp4\"\n autoPlay\n muted\n loop\n playsInline\n></video>\n```\n";
@@ -34,6 +34,21 @@ Embed images in your Markdown content using HTML syntax.
34
34
  <img src="https://docs.doccupine.com/demo.png" alt="Alt text">
35
35
  \`\`\`
36
36
 
37
+ ### Theme-aware images
38
+ Show different images depending on whether the user is in light or dark mode. Add the \`light-only\` or \`dark-only\` className to display an image exclusively in that theme.
39
+
40
+ \`\`\`md
41
+ <img className="light-only" src="/images/diagram-light.png" alt="Diagram">
42
+ <img className="dark-only" src="/images/diagram-dark.png" alt="Diagram">
43
+ \`\`\`
44
+
45
+ <img className="light-only" src="https://docs.doccupine.com/demo.png" alt="This image is only visible in light mode">
46
+ <img className="dark-only" src="https://docs.doccupine.com/demo.png" alt="This image is only visible in dark mode" style={{ filter: "invert(1)" }}>
47
+
48
+ <Callout type="note">
49
+ The \`light-only\` and \`dark-only\` classes work on any element, not just images. You can use them on videos, iframes, or wrapper divs too.
50
+ </Callout>
51
+
37
52
  ## Videos
38
53
  Videos add a dynamic element to your documentation, engaging your audience and providing a more immersive experience.
39
54
 
@@ -10,21 +10,21 @@ export const packageJsonTemplate = JSON.stringify({
10
10
  format: "prettier --write .",
11
11
  },
12
12
  dependencies: {
13
- "@langchain/anthropic": "^1.3.20",
14
- "@langchain/core": "^1.1.28",
15
- "@langchain/google-genai": "^2.1.20",
16
- "@langchain/openai": "^1.2.10",
13
+ "@langchain/anthropic": "^1.3.23",
14
+ "@langchain/core": "^1.1.32",
15
+ "@langchain/google-genai": "^2.1.25",
16
+ "@langchain/openai": "^1.2.13",
17
17
  "@mdx-js/react": "^3.1.1",
18
18
  "@modelcontextprotocol/sdk": "^1.27.1",
19
- "@posthog/react": "^1.8.1",
19
+ "@posthog/react": "^1.8.2",
20
20
  "cherry-styled-components": "^0.1.13",
21
- langchain: "^1.2.27",
22
- "lucide-react": "^0.575.0",
21
+ langchain: "^1.2.31",
22
+ "lucide-react": "^0.577.0",
23
23
  next: "16.1.6",
24
24
  "next-mdx-remote": "^6.0.0",
25
25
  polished: "^4.3.1",
26
- "posthog-js": "^1.354.0",
27
- "posthog-node": "^5.26.0",
26
+ "posthog-js": "^1.360.1",
27
+ "posthog-node": "^5.28.1",
28
28
  react: "19.2.4",
29
29
  "react-dom": "19.2.4",
30
30
  "rehype-highlight": "^7.0.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doccupine",
3
- "version": "0.0.71",
3
+ "version": "0.0.72",
4
4
  "description": "Free and open-source documentation platform. Write MDX, get a production-ready site with AI chat, built-in components, and an MCP server - in one command.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -37,7 +37,7 @@
37
37
  "chalk": "^5.6.2",
38
38
  "chokidar": "^5.0.0",
39
39
  "commander": "^14.0.3",
40
- "fs-extra": "^11.3.3",
40
+ "fs-extra": "^11.3.4",
41
41
  "gray-matter": "^4.0.3",
42
42
  "next": "^16.1.6",
43
43
  "prompts": "^2.4.2",
@@ -47,7 +47,7 @@
47
47
  "devDependencies": {
48
48
  "@types/chokidar": "^2.1.7",
49
49
  "@types/fs-extra": "^11.0.4",
50
- "@types/node": "^25.3.0",
50
+ "@types/node": "^25.4.0",
51
51
  "@types/prompts": "^2.4.9",
52
52
  "prettier": "^3.8.1",
53
53
  "typescript": "^5.9.3",