/*! * ======================================================================== * @rzl-zone/next-kit * ------------------------------------------------------------------------ * Version: `0.10.4` * Author: `Rizalvin Dwiky ` * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/next-kit` * ======================================================================== */ import { shallowCompareProps } from "@rzl-zone/core/comparison/shallow-compare-props"; import { isDevEnv, isPreviewEnv, isProdEnv, isQaEnv, isStagingEnv, isTestEnv, nodeEnv } from "@rzl-zone/core/env/node"; import { mergeRefs } from "@rzl-zone/core-react/utils/merge-refs"; import { mergeProps } from "@rzl-zone/core-react/utils/merge-props"; import { IsAny } from "@rzl-zone/ts-types-plus"; /** ------------------------------------------------------------------- * * ***Checks whether a given path is within the configured Next.js * router base path.*** * -------------------------------------------------------------------- * * This utility is typically used internally by the router to ensure * that navigation targets respect the configured base path. * * - **Behavior:** * - Delegates prefix matching to `pathHasPrefix` * - Uses the runtime router base path * * @param path - The path to check. * * @returns `true` if the path includes the base path, otherwise `false`. */ declare function hasBasePathNextJs(path: string): boolean; /** ------------------------------------------------------------------- * * ***Determines whether a given URL is routable by the Next.js router * in the browser.*** * -------------------------------------------------------------------- * * This function distinguishes between local (same-origin) URLs and * external URLs, ensuring compatibility with Next.js client-side routing. * * - **Behavior:** * - Treats relative URLs as local * - Resolves absolute URLs against the current origin * - Ensures the resolved URL matches the current origin * - Ensures the pathname respects the configured base path * - Returns `false` for invalid URLs * * @param url - The URL string to evaluate. * * @returns `true` if the URL is local and routable, otherwise `false`. * * @example * ```ts * isLocalURLNextJs("/about"); // true * isLocalURLNextJs("https://external.com"); // false * ``` */ declare function isLocalURLNextJs(url: string): boolean; type OptionsCreateBeApiUrl = { /** * The prefix pathname api url, e.g:`"http://localhost.com/your-target-prefix-entri-point-api-is-here"`, default: `"/api"`. * * @default "/api" */ prefix?: string; /** * Option to getting `prefix` and `pathname` of api url only `(removing origin base api url)`, default: `true`. * * @default true */ withOrigin?: boolean; }; /** --------------------------------------------------- * * ***Utility for NextJS: `createBeApiUrl`.*** * --------------------------------------------------- * * **Constructs a backend API URL by appending a given pathname to the base API URL.** * - **ℹ️ Note:** * - This function builds on top of `getBeApiUrl()`. * - **Determines the base API URL from:** * - `NEXT_PUBLIC_BACKEND_API_URL` environment variable (or defaults to `"http://localhost:8000"`). * - Automatically appends `NEXT_PUBLIC_PORT_BE` if the base URL does not already include a port. * - **Features of this function:** * - Allows customizing the API path with an optional `prefix` (defaults to `"/api"`). * - Can include or exclude the origin (protocol + host) via `withOrigin`. * - Normalizes paths to avoid duplicate slashes. * - ***⚠️ Warning:*** * - ***This function only support when using ***[`NextJS`](https://nextjs.org/)***.*** * * @param {string|null|undefined} pathname - The API endpoint path (e.g., `/users` or `/v1/posts`), defaultValue: `""`. * @param {OptionsCreateBeApiUrl} [options] - Configuration options. * @param {OptionsCreateBeApiUrl["prefix"]} [options.prefix="/api"] - The prefix for the API path (default is `"/api"`). * @param {OptionsCreateBeApiUrl["withOrigin"]} [options.withOrigin=true] - Whether to include the full base URL or return only the API path. * * @returns {string} The formatted API URL. * * @throws **{@link TypeError | `TypeError`}** if `withOrigin` is not a boolean. * @throws **{@link TypeError | `TypeError`}** if `prefix` and `pathname` is not a string. * @throws **{@link Error | `Error`}** if constructing the API URL fails due to an invalid base URL. * * @example * createBeApiUrl("/users"); * // ➔ "http://localhost:8000/api/users" * * createBeApiUrl("/api/users"); * // ➔ "http://localhost:8000/api/users" * * createBeApiUrl("/v1", { prefix: "/v1" }); * // ➔ "http://localhost:8000/v1" * * createBeApiUrl("/v1/users"); * // ➔ "http://localhost:8000/api/v1/users" * * createBeApiUrl("/v1/users", { prefix: "/v1" }); * // ➔ "http://localhost:8000/v1/users" * * createBeApiUrl("/users", { withOrigin: false }); * // ➔ "/api/users" * * createBeApiUrl(null, { withOrigin: false }); * // ➔ "/api" * * createBeApiUrl(undefined, { withOrigin: false }); * // ➔ "/api" */ declare const createBeApiUrl: ( /** * The pathname api url, e.g:`"http://localhost.com/your-target-prefix-entri-point-api-is-here/your-target-pathname-is-here"`. * * @default "" */ pathname: string | null | undefined, options?: OptionsCreateBeApiUrl) => string; /** --------------------------------------------------------------------- * * ***Extracts dynamic route parameters from a given route string.*** * ---------------------------------------------------------------------- * * **This utility type recursively searches for dynamic segments within a route, * extracting each parameter and constructing an object where each key represents * a dynamic segment and its value is of type `string`.** * - ***⚠️ Warning:*** * - ***This types only support when using ***[`NextJS`](https://nextjs.org/)***.*** * * @template T - The route string containing potential dynamic segments. * * @example * ```ts * type Params1 = ExtractRouteParams<"/user/[id]">; * // ➔ { id: string } * * type Params2 = ExtractRouteParams<"/post/[slug]/comment/[commentId]">; * // ➔ { slug: string; commentId: string } * * type Params3 = ExtractRouteParams<"/dashboard">; * // ➔ {} (no dynamic parameters) * ``` */ type ExtractRouteParams = T extends string ? HasDynamicSegments extends true ? T extends `${infer _Start}[${infer Param}]${infer Rest}` ? { [K in Param | keyof ExtractRouteParams]: string } : unknown : unknown : unknown; /** --------------------------------------------------------- * * ***Determines whether a given route contains dynamic segments.*** * --------------------------------------------------------- * **This type checks if the route includes at least one `[param]` pattern. * If it does, the result is `true`, otherwise `false`.** * - ***⚠️ Warning:*** * - ***This types only support when using ***[`NextJS`](https://nextjs.org/)***.*** * @template T - The route string to be evaluated. * @example * ```ts * type HasParams1 = HasDynamicSegments<"/user/[id]">; * // ➔ true * type HasParams2 = HasDynamicSegments<"/settings/profile">; * // ➔ false * type HasParams3 = HasDynamicSegments<"/blog/[category]/[slug]">; * // ➔ true * ``` */ type HasDynamicSegments = T extends `${string}[${string}]${string}` ? true : false; type GenerateRouteResult = true extends IsAny ? unknown : T extends string ? string : unknown; /** --------------------------------- * * ***Utility for NextJS: `generateRoute`.*** * --------------------------------- * **Generates a URL by replacing dynamic route parameters with provided values.** * - ***⚠️ Warning:*** * - ***This function only support when using ***[`NextJS`](https://nextjs.org/)***.*** * @template T - The route string containing dynamic segments in the format `[param]`. * @param {T} route - The route string containing dynamic segments. * @param {ExtractRouteParams} [params] - An object containing key-value pairs that match the dynamic segments in the route. * @returns {string} The formatted URL with all dynamic segments replaced. * @throws **{@link Error | `Error`}** if the route contains dynamic segments but no parameters object is provided. * @throws **{@link Error | `Error`}** if a required parameter is missing from the `params` object. * @throws **{@link Error | `Error`}** if a parameter value is an empty string. * @throws **{@link Error | `Error`}** if any parameter contains invalid characters like `?`, `&`, `=`, `#`, `/`, spaces, `'`, `"`, `(`, `)`, `+`, `;`, `%`, `@`, or `:`, which can cause URL issues. * @example * // Basic usage * generateRoute("/user/[id]", { id: "123" }); * // ➔ "/user/123" * * // No dynamic segments, returns as-is * generateRoute("/dashboard"); * // ➔ "/dashboard" * * // Throws an error due to missing parameters object * generateRoute("/profile/[username]"); * // ➔ ❌ Error: ❌ Missing parameters object for route: "/profile/[username]" * * // Throws an error due to an empty parameter value * generateRoute("/post/[category]/[slug]", { category: "tech", slug: "" }); * // ➔ ❌ Error: ❌ Parameter "slug" cannot be empty in route: "/post/[category]/[slug]" * * // Throws an error due to parameter containing invalid characters * generateRoute("/search/[query]", { query: "how to?learn" }); * // ➔ ❌ Error: ❌ Parameter "query" contains invalid character "?" in route: "/search/[query]" * * // Handles leading/trailing slashes correctly * generateRoute("/blog/[category]/[slug]", { category: "/news/", slug: "/latest-update/" }); * // ➔ ❌ Error: ❌ Parameter "category" and "slug" contains slashes "/" which is not allowed. */ declare function generateRoute(route: T extends string ? HasDynamicSegments extends true ? T : never : never, params: T extends string ? ExtractRouteParams : undefined): GenerateRouteResult; declare function generateRoute(route: T extends string ? T : never, params?: Extract, Record>): GenerateRouteResult; declare function generateRoute(route: T extends string ? HasDynamicSegments extends true ? T : unknown : unknown, params?: T extends string ? ExtractRouteParams : undefined): unknown; /** --------------------------------------------------- * * ***Utility for NextJS: `getBaseUrl`.*** * --------------------------------------------------- * **Retrieves the base URL of the application.** * - **Behavior:** * - It determines the base URL from the `NEXT_PUBLIC_BASE_URL` environment variable. * - If `NEXT_PUBLIC_BASE_URL` is not set, it defaults to `"http://localhost:3000"`. * - If `NEXT_PUBLIC_BASE_URL` does **not** contain a port, it appends one from `NEXT_PUBLIC_PORT_FE` if available. * - Ensures the final URL is valid and normalized (no trailing slashes). * * - ***⚠️ Warning:*** * - ***This function only support when using ***[`NextJS`](https://nextjs.org/)***.*** * * @returns {string} The resolved base URL of the application. * * @throws **{@link Error | `Error`}** if the constructed URL is invalid or malformed. * * @example * // With environment variable set at `*.env` file * NEXT_PUBLIC_BASE_URL = "https://example.com"; * getBaseUrl(); * // ➔ "https://example.com" * * // With custom port via NEXT_PUBLIC_PORT_FE at `*.env` file * NEXT_PUBLIC_BASE_URL = "http://localhost"; * NEXT_PUBLIC_PORT_FE = "4000"; * getBaseUrl(); * // ➔ "http://localhost:4000" * * // Without environment variable at `*.env` file * delete NEXT_PUBLIC_BASE_URL; * getBaseUrl(); * // ➔ "http://localhost:3000" */ declare const getBaseUrl: () => string; type OptionsGetBeApiUrl = { /** * ***The Suffix origin base api url, e.g:`http://localhost.com/api`, default: `"/"`.*** * * @default "/" */ suffix?: string; }; /** --------------------------------------------------- * * ***Utility for NextJS: `getBeApiUrl`.*** * --------------------------------------------------- * * **This function determines the backend API base URL from the `NEXT_PUBLIC_BACKEND_API_URL` environment variable (retrieves the base API URL of the backend).** * - **Behavior:** * - If the variable is not set, it defaults to `"http://localhost:8000"`. * - It also allows adding an optional suffix to the returned URL. * - ***⚠️ Warning:*** * - ***This function only support when using ***[`NextJS`](https://nextjs.org/)***.*** * * @description * This function determines the backend API base URL from the `NEXT_PUBLIC_BACKEND_API_URL` environment variable. * - If `NEXT_PUBLIC_BACKEND_API_URL` is not set, it defaults to `"http://localhost:8000"`. * - If `NEXT_PUBLIC_BACKEND_API_URL` does **not** contain a port, it appends one from `NEXT_PUBLIC_PORT_BE` if available. * - Supports appending optional suffix (like `"/api"`). * * @param {OptionsGetBeApiUrl|undefined} options - Configuration options. * @param {OptionsGetBeApiUrl["suffix"]} [options.suffix="/"] - The suffix to append to the base API URL. * * @returns {string} The formatted backend API base URL. * * @throws **{@link TypeError | `TypeError`}** if `suffix` is not a `string`. * @throws **{@link Error | `Error`}** if `NEXT_PUBLIC_BACKEND_API_URL` is invalid. * * @example * // With NEXT_PUBLIC_BACKEND_API_URL set at `*.env` file * NEXT_PUBLIC_BACKEND_API_URL = "https://api.example.com"; * getBeApiUrl(); * // ➔ "https://api.example.com/" * * // With NEXT_PUBLIC_BACKEND_API_URL but no port, using NEXT_PUBLIC_PORT_BE at `*.env` file * NEXT_PUBLIC_BACKEND_API_URL = "http://localhost"; * NEXT_PUBLIC_PORT_BE = "5000"; * getBeApiUrl({ suffix: "/api" }); * // ➔ "http://localhost:5000/api" * * // Without NEXT_PUBLIC_BACKEND_API_URL at `*.env` file (defaults to localhost:8000) * delete NEXT_PUBLIC_BACKEND_API_URL; * getBeApiUrl({ suffix: "/v1" }); * // ➔ "http://localhost:8000/v1" */ declare const getBeApiUrl: (options?: OptionsGetBeApiUrl) => string; export { ExtractRouteParams, HasDynamicSegments, createBeApiUrl, generateRoute, getBaseUrl, getBeApiUrl, hasBasePathNextJs, isDevEnv, isLocalURLNextJs, isPreviewEnv, isProdEnv, isQaEnv, isStagingEnv, isTestEnv, mergeProps, mergeRefs, nodeEnv, shallowCompareProps };