From df618fe1818c228a6422a05ae6f992f06b2433c4 Mon Sep 17 00:00:00 2001 From: esemyonov <132259164+esemyonov@users.noreply.github.com> Date: Fri, 15 Dec 2023 13:13:57 +0600 Subject: [PATCH] Refactoring (#284) * refactor: removed theme selector * refactor: navigation styles * refactor: intro page * refactor: redirects * refactor: intro page * fix: minor fixes --- next.config.mjs | 12 +++++ package-lock.json | 28 ++++++++-- package.json | 1 + src/app/articles/node-modules/page.tsx | 4 +- src/app/intro/page.tsx | 65 +++++++++++++++++++++++ src/app/page.tsx | 37 ------------- src/app/policies/[slug]/page.tsx | 2 +- src/components/DocsHeader.tsx | 4 +- src/components/DocsLayout.tsx | 10 ++-- src/components/MobileTableOfContents.tsx | 2 +- src/components/Navigation.tsx | 2 +- src/components/PrevNextLinks.tsx | 4 +- src/components/QuickLinks.tsx | 28 ++++++---- src/components/Search.tsx | 2 +- src/components/TableOfContents.tsx | 2 +- src/components/shared/article/Support.tsx | 40 +++++++------- src/lib/markdown/mdx.ts | 2 +- src/lib/policies.ts | 6 +-- src/lib/{interfaces.ts => types.ts} | 39 ++++++++------ types.d.ts | 2 +- 20 files changed, 187 insertions(+), 105 deletions(-) create mode 100644 src/app/intro/page.tsx delete mode 100644 src/app/page.tsx rename src/lib/{interfaces.ts => types.ts} (53%) diff --git a/next.config.mjs b/next.config.mjs index 5a7bead9..0aafacc0 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,6 +1,8 @@ import withNavigation from "./src/build/navigation.mjs"; import withSearch from "./src/build/search.mjs"; +const protectedRoutes = ["/", "/docs"]; + /** @type {import('next').NextConfig} */ const nextConfig = { swcMinify: true, @@ -17,6 +19,16 @@ const nextConfig = { }, ], }, + async redirects() { + return [ + ...protectedRoutes.map((source) => ({ + source, + destination: "/docs/intro", + permanent: true, + basePath: false, + })), + ]; + }, webpack(config) { config.module.rules.push({ test: /\.svg$/i, diff --git a/package-lock.json b/package-lock.json index c51b0cd4..b23491ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,7 @@ "jsonc-parser": "^3.2.0", "mdast-util-to-string": "^4.0.0", "mermaid": "^10.5.0", + "nanoid": "^5.0.4", "next": "^13.5.4", "next-mdx-remote": "^4.4.1", "next-sitemap": "^4.2.3", @@ -12034,9 +12035,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.4.tgz", + "integrity": "sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==", "funding": [ { "type": "github", @@ -12044,10 +12045,10 @@ } ], "bin": { - "nanoid": "bin/nanoid.cjs" + "nanoid": "bin/nanoid.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "^18 || >=20" } }, "node_modules/napi-build-utils": { @@ -13665,6 +13666,23 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", diff --git a/package.json b/package.json index 2e877c08..8e0674e3 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "jsonc-parser": "^3.2.0", "mdast-util-to-string": "^4.0.0", "mermaid": "^10.5.0", + "nanoid": "^5.0.4", "next": "^13.5.4", "next-mdx-remote": "^4.4.1", "next-sitemap": "^4.2.3", diff --git a/src/app/articles/node-modules/page.tsx b/src/app/articles/node-modules/page.tsx index 6a31ed63..f05f3cf8 100644 --- a/src/app/articles/node-modules/page.tsx +++ b/src/app/articles/node-modules/page.tsx @@ -1,5 +1,5 @@ import { DocsLayout } from "@/components/DocsLayout"; -import { Bundle } from "@/lib/interfaces"; +import { Bundle } from "@/lib/types"; import { readFile } from "fs/promises"; import { Metadata } from "next"; import Link from "next/link"; @@ -17,7 +17,7 @@ export default async function Page() { ).bundles.filter((bundle) => bundle.public); return ( - +

Zuplo generally supports node modules, but to ensure the security and performance of each API Gateway we must approve each module. This diff --git a/src/app/intro/page.tsx b/src/app/intro/page.tsx new file mode 100644 index 00000000..6064ce96 --- /dev/null +++ b/src/app/intro/page.tsx @@ -0,0 +1,65 @@ +import { DocsLayout } from "@/components/DocsLayout"; +import { QuickLink, QuickLinks } from "@/components/QuickLinks"; +import { QuickLinkItem } from "@/lib/types"; +import { nanoid } from "nanoid"; + +export default async function Page() { + const overviewItems: Array = [ + { + id: nanoid(), + title: "What is Zuplo?", + href: "/articles/what-is-zuplo", + icon: "installation", + }, + { + id: nanoid(), + title: "Who uses Zuplo, and why?", + href: "/articles/who-uses-and-why", + icon: "installation", + }, + { + id: nanoid(), + title: "Zuplo in your stack", + href: "/articles/zuplo-in-your-stack", + icon: "installation", + }, + ]; + + const gettingStartedItems: Array = [ + { + id: nanoid(), + title: "Step 1 - Setup Basic Gateway", + href: "/articles/step-1-setup-basic-gateway", + icon: "installation", + }, + { + id: nanoid(), + title: "Step 2 - API Key Auth", + href: "/articles/step-2-add-api-key-auth", + icon: "installation", + }, + { + id: nanoid(), + title: "Step 3 - Rate Limiting", + href: "/articles/step-3-add-rate-limiting", + icon: "installation", + }, + { + id: nanoid(), + title: "Step 4 - Deploying to the Edge", + href: "/articles/step-4-deploying-to-the-edge", + icon: "installation", + }, + ]; + + return ( + + Learn how to use Zuplo to add API-key management, developer documentation, + and rate-limiting, for any stack. +

Overview

+ +

Getting Started

+ +
+ ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx deleted file mode 100644 index 81edb58d..00000000 --- a/src/app/page.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { DocsLayout } from "@/components/DocsLayout"; -import { QuickLink, QuickLinks } from "@/components/QuickLinks"; - -export default async function Page() { - return ( - - Learn how to use Zuplo to add API-key management, developer documentation, - and rate-limiting, for any stack. - - {" "} - - - - - - ); -} diff --git a/src/app/policies/[slug]/page.tsx b/src/app/policies/[slug]/page.tsx index 67672552..88fe2d8f 100644 --- a/src/app/policies/[slug]/page.tsx +++ b/src/app/policies/[slug]/page.tsx @@ -1,5 +1,5 @@ import { DocsLayout } from "@/components/DocsLayout"; -import { Section } from "@/lib/interfaces"; +import { Section } from "@/lib/types"; import { getAllPolicies, getPolicy } from "@/lib/policies"; import { getHighlighter } from "shiki"; diff --git a/src/components/DocsHeader.tsx b/src/components/DocsHeader.tsx index 6975ce5c..c900b7a1 100644 --- a/src/components/DocsHeader.tsx +++ b/src/components/DocsHeader.tsx @@ -3,7 +3,7 @@ import { usePathname } from "next/navigation"; import { navigation } from "@/build/navigation.mjs"; -import { NavCategory, NavItem, Section } from "@/lib/interfaces"; +import { NavCategory, NavItem, Section } from "@/lib/types"; import Link from "next/link"; import ChevronRightIcon from "@/components/svgs/chevron-right.svg"; import { MobileTableOfContents } from "@/components/MobileTableOfContents"; @@ -34,7 +34,7 @@ export function DocsHeader({ return (
- Home + Home {section && ( <> diff --git a/src/components/DocsLayout.tsx b/src/components/DocsLayout.tsx index 9152c61d..d9a04895 100644 --- a/src/components/DocsLayout.tsx +++ b/src/components/DocsLayout.tsx @@ -5,16 +5,18 @@ import { Prose } from "@/components/Prose"; import { TableOfContents } from "@/components/TableOfContents"; import ArticleRate from "@/components/shared/article/Rate"; import ArticleSupport from "@/components/shared/article/Support"; -import { Section } from "@/lib/interfaces"; +import { Section } from "@/lib/types"; export function DocsLayout({ children, frontmatter: { title }, - sections, + sections = [], + useRateSection = true, }: { children: React.ReactNode; frontmatter: { title?: string }; - sections: Section[]; + sections?: Array
; + useRateSection?: boolean; }) { return ( <> @@ -24,7 +26,7 @@ export function DocsLayout({ {children} - + {useRateSection && }
diff --git a/src/components/MobileTableOfContents.tsx b/src/components/MobileTableOfContents.tsx index 6c36368d..172d8d17 100644 --- a/src/components/MobileTableOfContents.tsx +++ b/src/components/MobileTableOfContents.tsx @@ -1,6 +1,6 @@ "use client"; -import { Section } from "@/lib/interfaces"; +import { Section } from "@/lib/types"; import { Listbox, Transition } from "@headlessui/react"; import clsx from "classnames"; import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/20/solid"; diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx index 7be575a8..ddd7a088 100644 --- a/src/components/Navigation.tsx +++ b/src/components/Navigation.tsx @@ -6,7 +6,7 @@ import ChevronDownIcon from "@/components/svgs/chevron-down.svg"; import ArrowIcon from "@/components/svgs/arrow.svg"; import { navigation } from "@/build/navigation.mjs"; -import { NavCategory, NavItem } from "@/lib/interfaces"; +import { NavCategory, NavItem } from "@/lib/types"; import { useState } from "react"; function SubNavSection({ diff --git a/src/components/PrevNextLinks.tsx b/src/components/PrevNextLinks.tsx index 7b8ca470..0a971ee1 100644 --- a/src/components/PrevNextLinks.tsx +++ b/src/components/PrevNextLinks.tsx @@ -1,7 +1,7 @@ "use client"; import { navigation } from "@/build/navigation.mjs"; -import { NavCategory, NavItem } from "@/lib/interfaces"; +import { NavCategory, NavItem } from "@/lib/types"; import clsx from "classnames"; import Link from "next/link"; import { usePathname } from "next/navigation"; @@ -70,7 +70,7 @@ export function PrevNextLinks() { } return ( -
+
{previousPage && "href" in previousPage && ( )} diff --git a/src/components/QuickLinks.tsx b/src/components/QuickLinks.tsx index 799c5830..a035301b 100644 --- a/src/components/QuickLinks.tsx +++ b/src/components/QuickLinks.tsx @@ -1,11 +1,19 @@ import Link from "next/link"; import { Icon } from "@/components/Icon"; +import { QuickLinkItem } from "@/lib/types"; -export function QuickLinks({ children }: { children: React.ReactNode }) { +export function QuickLinks({ items }: { items: Array }) { return ( -
- {children} +
+ {items.map((item) => ( + + ))}
); } @@ -17,24 +25,26 @@ export function QuickLink({ icon, }: { title: string; - description: string; + description?: string; href: string; icon: React.ComponentProps["icon"]; }) { return (
-
+
-

+

{title}

-

- {description} -

+ {description && ( +

+ {description} +

+ )}
); diff --git a/src/components/Search.tsx b/src/components/Search.tsx index 02a657a6..1985d2d1 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -2,7 +2,7 @@ import { navigation } from "@/build/navigation.mjs"; import { type Result } from "@/build/search.mjs"; -import { NavCategory, NavItem } from "@/lib/interfaces"; +import { NavCategory, NavItem } from "@/lib/types"; import { createAutocomplete, type AutocompleteApi, diff --git a/src/components/TableOfContents.tsx b/src/components/TableOfContents.tsx index 4c4a11db..33f122dc 100644 --- a/src/components/TableOfContents.tsx +++ b/src/components/TableOfContents.tsx @@ -4,7 +4,7 @@ import clsx from "classnames"; import Link from "next/link"; import { useCallback, useEffect, useState } from "react"; -import { type Section } from "@/lib/interfaces"; +import { type Section } from "@/lib/types"; export function TableOfContents({ tableOfContents, diff --git a/src/components/shared/article/Support.tsx b/src/components/shared/article/Support.tsx index 745cf8fc..bb40ad55 100644 --- a/src/components/shared/article/Support.tsx +++ b/src/components/shared/article/Support.tsx @@ -7,25 +7,27 @@ export default function ArticleSupport() { "font-bold tracking-wider text-pink transition-colors hover:text-pink-hover"; return ( -
-
- - Do you have any questions? - - Contact us - -
-
- - Check out our - - product changelog - +
+
+
+ + Do you have any questions? + + Contact us + +
+
+ + Check out our + + product changelog + +
); diff --git a/src/lib/markdown/mdx.ts b/src/lib/markdown/mdx.ts index aec11f1b..57c1403d 100644 --- a/src/lib/markdown/mdx.ts +++ b/src/lib/markdown/mdx.ts @@ -1,5 +1,5 @@ import components from "@/components/mdx"; -import { Section } from "@/lib/interfaces"; +import { Section } from "@/lib/types"; import remarkTransformLink from "@/lib/markdown/md-link"; import remarkStaticImage from "@/lib/markdown/static-image"; import fs from "fs/promises"; diff --git a/src/lib/policies.ts b/src/lib/policies.ts index a3f8428e..f52e6dec 100644 --- a/src/lib/policies.ts +++ b/src/lib/policies.ts @@ -4,7 +4,7 @@ import { readFile } from "fs/promises"; import { glob } from "glob"; import { JSONSchema7Definition } from "json-schema"; import path from "path"; -import { PolicyMeta, PolicySchema, Section } from "./interfaces"; +import { PolicyMeta, PolicySchema, Section } from "./types"; const policiesDir = path.resolve(process.cwd(), "./policies"); @@ -88,8 +88,8 @@ export async function getPolicy(policyId: string) { async function processProperties( properties: | { - [key: string]: JSONSchema7Definition; - } + [key: string]: JSONSchema7Definition; + } | undefined, ) { if (!properties) { diff --git a/src/lib/interfaces.ts b/src/lib/types.ts similarity index 53% rename from src/lib/interfaces.ts rename to src/lib/types.ts index e8b50663..22da1d86 100644 --- a/src/lib/interfaces.ts +++ b/src/lib/types.ts @@ -1,47 +1,56 @@ import { JSONSchema7 } from "json-schema"; +import { Icon } from "@/components/Icon"; -export interface PolicyMeta { +export type PolicyMeta = { name: string; isPreview: boolean; isPaidAddOn: boolean; isDeprecated: boolean; - fakePolicyUrl: string | undefined; + fakePolicyUrl?: string; href: string; id: string; icon: string; -} +}; -export interface PolicySchema extends JSONSchema7 { +export type PolicySchema = JSONSchema7 & { isPreview?: boolean; isDeprecated?: boolean; isPaidAddOn?: boolean; fakePolicyUrl?: string; isCustom?: boolean; -} +}; -export interface Section { +export type Section = { id: string; title: string; level: number; children: Array
; -} +}; -export interface Bundle { +export type Bundle = { name: string; version: string; types: string; - files: string[]; + files: Array; description: string; url: string; public: boolean; -} +}; -export interface NavCategory { +export type NavCategory = { label: string; - items: (NavCategory | NavItem)[]; -} + items: Array; +}; -export interface NavItem { +export type NavItem = { label: string; href: string; -} +}; + +export type QuickLinkItem = { + id: string; + title: string; + description?: string; + href: string; + icon: React.ComponentProps["icon"]; +}; diff --git a/types.d.ts b/types.d.ts index dfafcc3c..d9f0bf18 100644 --- a/types.d.ts +++ b/types.d.ts @@ -1,7 +1,7 @@ declare module "remark-admonitions"; declare module "badwords-list"; declare module "simple-functional-loader"; -import { NavCategory } from "@/lib/interfaces"; +import { NavCategory } from "@/lib/types"; import { type SearchOptions } from "flexsearch"; declare module "@/build/search.mjs" {